bzoj1047理想的正方形

題目連接 php

記念又雙叒叕的一道暴力碾標算的題
咱們考慮純暴力
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,n;
int map[1010][1010];
int ans=0x3f3f3f3f;
int main()
{
 scanf("%d%d%d",&a,&b,&n);
 for(int i=1;i<=a;i++)
   for(int j=1;j<=b;j++)
  scanf("%d",&map[i][j]);
    for(int i=1;i+n-1<=a;i++)
      for(int j=1;j+n-1<=b;j++){
  int maxx=0,minn=0x3f3f3f3f;
     for(int l=i;l<=n+i-1;l++)
          for(int r=j;r<=n+j-1;r++)
            maxx=max(maxx,map[l][r]),
            minn=min(minn,map[l][r]);
  ans=min(ans,maxx-minn);
    }
    printf("%d",ans);
    return 20020902;
}

 

而後顯然,果斷$TLE$
那麼咱們考慮怎麼優化暴力
別跟我提什麼數據結構啊,單調隊列
本小可愛一個也不會
咱們回頭看看這兩道題 洛谷P2038   洛谷P2280
這兩道題也是矩陣,而後咱們是用的維護二維前綴和來找的在一個矩形內的某些數值
那麼,這道題是否是也能夠相似的作呢?
因爲詢問的都是正方形,
咱們能夠預處理出來
全部正方形的最大最小值
($ps:$從$(1,1)$開始計數)
定義$maxx[i][j][k]$表示以$(i,j)$爲左上端點,而後邊長爲$k$的正方形最大值,$minn[i][j][k]$表示最小。
經過類比上兩道題,還有畫圖,得出
$$maxx[i][j][k]=max(max(maxx[i][j][k-1],maxx[i+1][j+1][k-1]),max(maxx[i][j+1][k-1],maxx[i+1][j][k-1]))$$
$$minn[i][j][k]=min(min(minn[i][j][k-1],minn[i+1][j+1][k-1]),min(minn[i][j+1][k-1],minn[i+1][j][k-1]))$$
因此,咱們能夠求出來$maxx[][][n],minn[][][n]$
而後枚舉左上角端點而後更新答案就行

別覺得這樣就行了
您寫完了以後本地編譯了麼?
是否是編譯未成功?
由於$maxx,minn$這樣要開$1001*1001*1001=1e9$辣麼大的數組
顯然開不下啊$qwq$
那怎麼辦?
涼拌啊!
發現咱們推$maxx,minn$的時候,每次只涉及到$k,k-1$,而且只涉及到$i+1,j+1,i,j$這幾個東東,因此能夠相似滾動數組優化,滾掉$k$這一維
而後又是省選題
開個$O2$也沒什麼大不了的
實際上是本寶寶懶得寫優化了
上代碼:
看,連$1kb$都不到
真是暴力碾標算的好題啊$qwq$
// luogu-judger-enable-o2
#pragma GCC optimize (2)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,n;
int map[1010][1010];
int maxx[1010][1010];
int minn[1010][1010];
int ans=0x3f3f3f3f;
int main()
{
    scanf("%d%d%d",&a,&b,&n);
    for(int i=1;i<=a;i++)
      for(int j=1;j<=b;j++)
        scanf("%d",&map[i][j]),
        maxx[i][j]=minn[i][j]=map[i][j];
    for(int k=2;k<=n;k++)
      for(int i=1;i+k<=a+1;i++)
        for(int j=1;j+k<=b+1;j++)
          maxx[i][j]=max(max(maxx[i][j],maxx[i+1][j+1]),max(maxx[i][j+1],maxx[i+1][j])),
          minn[i][j]=min(min(minn[i][j],minn[i+1][j+1]),min(minn[i][j+1],minn[i+1][j])),
          ans=k==n?min(ans,maxx[i][j]-minn[i][j]):0x3f3f3f3f;
    printf("%d",ans);
    return 0;
}
/*
5   4   2
1   2   5   6
0   17  16  0
16  17  2   1
2   10  2   1
1   2   2   2
*/
相關文章
相關標籤/搜索