【洛谷习题】最大正方形

题目链接:https://www.luogu.org/problemnew/show/P1387


 

最近学OI有点过火,今早上愣是没睡醒,上午的自习就没有了!不过还是很开心,连A三道DP水题。

这个题的话,思路比较清晰。我们想知道有没有边长为l的正方形,肯定要先知道有没有边长为l-1的正方形。我们枚举一个正方形的左上角,然后搬着一个边长为l-1的正方形在四个角上跑,如果这四个角上的小正方形全是1,那么这个边长为l的正方形肯定也全是1,否则取其中最大的。描述的有点凌乱,看代码就好了。一开始傻了一般开了一个四维数组保存正方形的四个顶点,这样是没有必要的,因为一个左上角的顶点和边长就能确定一个正方形。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int mmax = 105;
 7 
 8 int map[mmax][mmax], dp[mmax][mmax][mmax];
 9 int main() {
10     int n, m, ans = 1;
11     scanf("%d%d", &n, &m);
12     for (int i = 1; i <= n; ++i)
13         for (int j = 1; j <= m; ++j) {
14             scanf("%d", &map[i][j]);
15             if (map[i][j]) dp[i][j][1] = 1;
16         }
17     for (int l = 2; l <= min(n,m); ++l) {
18         for (int i = 1; i <= n - l + 1; ++i)
19             for (int j = 1; j <= m - l + 1; ++j) {
20                 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)
21                     dp[i][j][l] = l;
22                 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])));
23                 ans = max(ans, dp[i][j][l]);
24             }
25         if (ans < l) break;
26     }
27     printf("%d", ans);
28     return 0;
29 }
AC代码

 

实际上,这样做也不算太优秀。我们可以定义dp[i][j]表示以(i,j)为右下角的最大正方形的边长。那么对于map[i][j]==1,则有dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1。显然是对的,每次考虑能否将(i,j)加入到已有的正方形中,那他一定可以加入以(i-1,j-1)、(i-1,j)、(i,j-1)为右下角的最大正方形中最小的那个,因为最大正方形要求里面全是1。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int mmax = 105;
 7 
 8 int dp[mmax][mmax];
 9 
10 int main() {
11     int n, m, point, ans = 0;
12     scanf("%d%d", &n, &m);
13     for (int i = 1; i <= n; ++i)
14         for (int j = 1; j <= m; ++j) {
15             scanf("%d", &point);
16             if (point) {
17                 dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1;
18                 ans = max(ans, dp[i][j]);
19             }
20         }
21     printf("%d", ans);
22     return 0;
23 }
AC代码(更优秀)

 

posted @ 2018-09-09 13:24  Mr^Kevin  阅读(156)  评论(0编辑  收藏  举报