题目链接:https://www.luogu.org/problemnew/show/P1387
最近学OI有点过火,今早上愣是没睡醒,上午的自习就没有了!不过还是很开心,连A三道DP水题。
这个题的话,思路比较清晰。我们想知道有没有边长为l的正方形,肯定要先知道有没有边长为l-1的正方形。我们枚举一个正方形的左上角,然后搬着一个边长为l-1的正方形在四个角上跑,如果这四个角上的小正方形全是1,那么这个边长为l的正方形肯定也全是1,否则取其中最大的。描述的有点凌乱,看代码就好了。一开始傻了一般开了一个四维数组保存正方形的四个顶点,这样是没有必要的,因为一个左上角的顶点和边长就能确定一个正方形。
1 #include<cstdio> 2 inline int max(int a,int b) {return a>b?a:b;} 3 inline int min(int a,int b) {return a<b?a:b;} 4 const int mmax=105; 5 int n,m,map[mmax][mmax],dp[mmax][mmax][mmax],ans=1; 6 int main() { 7 scanf("%d%d",&n,&m); 8 for(int i=1;i<=n;++i) 9 for(int j=1;j<=m;++j) { 10 scanf("%d",&map[i][j]); 11 if(map[i][j]) dp[i][j][1]=1; 12 } 13 for(int l=2;l<=min(n,m);++l) { 14 for(int i=1;i<=n-l+1;++i) 15 for(int j=1;j<=m-l+1;++j) { 16 if(dp[i][j][l-1]==l-1&&dp[i][j+1][l-1]==l-1&&dp[i+1][j][l-1]==l-1&&dp[i+1][j+1][l-1]==l-1) 17 dp[i][j][l]=l; 18 else dp[i][j][l]=max(dp[i][j][l-1],max(dp[i][j+1][l-1],max(dp[i+1][j][l-1],dp[i+1][j+1][l-1]))); 19 ans=max(ans,dp[i][j][l]); 20 } 21 if(ans<l) break; 22 } 23 printf("%d",ans); 24 return 0; 25 }