CSU 1424 Qz’s Maximum All One Square

  原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1424

  逐渐找到做这种题的感觉了。

  二分法。g[i][j]存储坐标(i, j)的值,s[i][j]存储的值为左上角为起始点(1,1),右下角为(i, j)的矩形区域内所有值的和,那么:

    s[i][j] = g[i][j] + s[i-1][j] + s[i][j-1] - s[i-1][j-1]

  扫描整个矩形,遇到为“1”的点就将其作为起点,开始二分边长,利用数组s在O(1)的时间复杂度内判断是否满足为由1组成的正方形,不管更新最大值即可。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define N 1005

int g[N][N], s[N][N];

int n, m;

bool ok(int i, int j, int mid)
{
    int t1 = mid * mid;
    int t2 = s[i+mid-1][j+mid-1] - s[i+mid-1][j-1] - s[i-1][j+mid-1] + s[i-1][j-1];
    return t1 == t2;
}

int bs(int i, int j)
{
    int l = 1, r = N;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(i + mid - 1 > m || j + mid - 1 > n)
            r = mid;
        else if(ok(i, j, mid))
            l = mid+1;
        else
            r = mid;
    }
    return (l-1) * (l-1);
}

int main()
{
    int ans;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d", &g[i][j]);
                
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                s[i][j] = g[i][j] + s[i-1][j] + s[i][j-1] - s[i-1][j-1];
        ans = 0;
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                if(g[i][j])
                    ans = max(ans, bs(i, j));
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2014-05-10 16:39  芒果布丁  阅读(219)  评论(0编辑  收藏  举报