在棋盘中查找所有可能的正方形,但不包括选定的单元格

时间:2018-10-24 21:41:35

标签: algorithm dynamic-programming combinatorics

我在寻找棋盘问题中的所有方格方面略有不同。

我知道我们可以从大小为8x8的棋盘上找到所有可能的正方形 前8个数字的平方和 1 ^ 2 + 2 ^ 2 + 3 ^ 2 + 4 ^ 2 ... 8 ^ 2

但是,如果有一些被典当占据的单元格,我们需要排除包含这些典当的所有正方形。

例如考虑在4x4矩阵下

。 。 。

。 。 。

。 x x。

。 。 。

总平方= 30-{1(4x4)+ 4(3x3)+ 6(2x2)+ 2(1x1)} = 30-13 = 17

我曾考虑使用DP解决它,但无法准确确定如何排除禁忌广场。

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以在N ^ 3中解决它。对于每个像元(x,y),您都需要一个函数来判断是否有一个空的正方形,高度为z,z从0到n,并且(右,下)为(x,y)。

现在的问题是如何创建此功能。

您可以使用部分和执行此操作。对于每个像元(x,y),将DP [x] [y] =典当数nr保存在矩形(0,0),(x,y)中。然后您可以在O(1)中回答该函数。

有用的链接:

https://en.wikipedia.org/wiki/Summed-area_table

编辑#1(n ^ 2logn):
我认为您可以通过在上面讨论的函数中对平方高度进行二进制搜索来压缩性能(N ^ 2 * log(N))。之所以起作用,是因为如果对于z = 10(意味着您可以在(x,y)中将高度为10的正方形与(底部,右)放在一起),那么显然您也可以对z = 9,8,7。 .1。

编辑#2(n ^ 2):
是的,您是对的,您可以在n ^ 2中完成它:)。想想上面的函数,问题是:如果我知道对(x-1,y),(x,y-1)和(x- 1,y-1)?就是这样:当前位置的最大z =(x-1,y),(x,y-1),(x-1,y-1)+ 1中的z最小值;

int n,m,dp[100][100],rs;
char a[100][100];

int main() {

    std::cin >> n >> m;
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=m; j++) {
            std::cin >> a[i][j];
        }
    }

    for (int i=1; i<=n; i++) {
        for (int j=1; j<=m; j++) {
            if (a[i][j] == 'x') continue;
            rs += dp[i][j] = min(dp[i-1][j], min(dp[i][j-1], dp[i-1][j-1])) + 1;
        }
    }

    std::cout << rs << std::endl;

    for (int i=1; i<=n; i++) {
        for (int j=1; j<=m; j++) std::cout << dp[i][j] << ' ';
        std::cout << endl;
    }

    return 0;
}

输出示例:

4 4
....
....
.xx.
....
17
1 1 1 1
1 2 2 2
1 0 0 1
1 1 1 1