刚开始没想到怎么折状态转移

后来jfdalao给我讲了一遍才会

因为正方形的大小受到端点是否有鱼的限制

所以我们设s1(s2)i,j表示i,j左边(上面)最多有几个0

令f i,j表示以i,j为右下端点并且对角线经过i,j的对角线最大值

显然只有ai,j为1是才能转移

另外因为对角线有两个方向

所以我们应正反求两次

(代码是看别人的)

//P1736 创意吃鱼法
#include<bits/stdc++.h>
using namespace std;
int a[2505][2505],f[2505][2505],s1[2505][2505],s2[2505][2505];
int main(){
    int n,m,ans=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            if(!a[i][j]){
                s1[i][j]=s1[i][j-1]+1;
                s2[i][j]=s2[i-1][j]+1;
            }
            if(a[i][j])
                f[i][j]=min(f[i-1][j-1],min(s1[i][j-1],s2[i-1][j]))+1;
            ans=max(ans,f[i][j]);
        }
    }
    memset(f,0,sizeof(f));
    memset(s1,0,sizeof(s1));
    memset(s2,0,sizeof(s2));
    for(int i=1;i<=n;i++){
        for(int j=m;j>=1;j--){
            if(!a[i][j]){
                s1[i][j]=s1[i][j+1]+1;
                s2[i][j]=s2[i-1][j]+1;
            }
            if(a[i][j])
                f[i][j]=min(f[i-1][j+1],min(s1[i][j+1],s2[i-1][j]))+1;
            ans=max(ans,f[i][j]);
        }
    }
    cout<<ans;
    return 0;
}
01-03 22:15