luogu1736_創意吃魚法_二維dp
阿新 • • 發佈:2018-11-08
題意
簡單來說,就是給你一個0/1矩陣,讓你找這樣一個正方形:一條對角線全是1,其他地方全是0,並使得這個矩陣的邊長最大
solution
- 考慮維護一個s1[i][j]表示從(i,j)開始,往上連續0的長度,s2[i][j]表示向左的
- 這樣向左斜的就這樣
f[i][j]=min(f[i-1][j-1],min(s1[i-1][j],s2[i][j-1]))+1;
- 向右斜的同理
code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #include<cstdlib> #include<ctime> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; inline int read(){ char ch=' ';int f=1;int x=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } const int N=3000; int f[N][N]; int s1[N][N];// up int s2[N][N]; int a[N][N]; int main() { int n,m; n=read();m=read(); int i,j; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { a[i][j]=read(); } } int ans=0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(!a[i][j]) { s1[i][j]=s1[i-1][j]+1; s2[i][j]=s2[i][j-1]+1; } else f[i][j]=min(f[i-1][j-1],min(s1[i-1][j],s2[i][j-1]))+1; ans=max(ans,f[i][j]); } } memset(s1,0,sizeof(0)); memset(s2,0,sizeof(0)); memset(f,0,sizeof(f)); for(i=1;i<=n;i++) { for(j=m;j>=1;j--) { if(!a[i][j]) { s1[i][j]=s1[i-1][j]+1; s2[i][j]=s2[i][j+1]+1; } else { f[i][j]=min(f[i-1][j+1],min(s1[i-1][j],s2[i][j+1]))+1; } ans=max(ans,f[i][j]); } } cout<<ans<<endl; return 0; }