欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[线性DP] 洛谷P1387 最大正方形(思维定势问题)

程序员文章站 2023-12-26 12:41:39
...

题目

LP1387

思路

本题的DP部分和代码实现都很简单,充分迎合了普及/提高-的难度。
但大家都是怎么想出怎么用DP的。。怎么想出状态是正方形的右小角的。。我怎么想不出来。。是OI的题无论什么难度思维难度都这么高吗。。还是我比较笨。。


1.状态定义:d(i,j),(i,j)作为一个正方形的右小角,所形成的正方形的最大边长。
2.状态转移方程:

d(i,j)=min{d(i1,j),d(i,j1),d(i1,j1)}+1



为什么状态会这样转移,需要画图
[线性DP] 洛谷P1387 最大正方形(思维定势问题)
大概就是这样。
我做不出来的原因是因为思考的方向不对,因为之前做的球场那道题(实际上本题也确实可以用技巧枚举做出来),就一直在想直接枚举正方形起始点不好,一直在想怎么枚举正方形的边。这只能说明,思维定势有好有坏,但在我做题量还非常少的情况下请谨慎的使用思维定势,别一看到某道题就说是另外一道题的翻版,这样往往连正确的做法都掌握不到
另外一个原因是,缺少足够的画图与推演。图上这个道理很明显,我就不相信自己要是半小时一直勾勾画画能想不出来,但是自己一直凭空想而不去动手。只能说,对于OI这种思维难度较高的活动,应尽自己所能更好的去想一个问题(比如画图),毕竟这不如数学或者物理那么简单,不是盯着题看凭空一想就能想出来的,需要实打实的推演。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 100 + 10;
int n, m, G[maxn][maxn], d[maxn][maxn];

int main() {
    scanf("%d%d", &n, &m);
    _rep(i, 1, n) _rep(j, 1, m) scanf("%d", &G[i][j]);

    int ans = 0;
    _rep(i, 1, n)
        _rep(j, 1, m)
            if (G[i][j] == 1) {
                d[i][j] = min(d[i - 1][j], min(d[i][j - 1], d[i - 1][j - 1])) + 1;
                ans = max(ans, d[i][j]);
            }

    printf("%d\n", ans);

    return 0;
}

上一篇:

下一篇: