首页 > 技术文章 > FZU2056 最大正方形(二分答案)

someblue 2014-10-24 11:07 原文

Problem 2056 最大正方形

Accept: 171    Submit: 516
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

现在有一个n*m的矩阵A,在A中找一个H*H的正方形,使得其面积最大且该正方形元素的和不大于 limit。

 Input

第一行一个整数T,表示有T组数据。

每组数据 第一行三个非负整数 n m limit

接着 n 行,每行 m 个整数。

 

0 < n <= 1000, 0 < m <= 1000, 0 <= limit <=100000000 0 <= A[i] <= 1000

 Output

对于每组数据,输出H*H。

 Sample Input

2 2 2 2 1 1 1 1 2 2 4 1 1 1 1

 Sample Output

1 4
 
 
题意: 略
思路: 二分答案 判断一下
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1e9;
const double eps = 1e-6;
const int N = 1010;
int cas = 1;

int n,m;
ll w[N][N],sum[N][N],limit;

void pre()
{
    memset(sum,0,sizeof(sum));
    scanf("%d%d%I64d",&n,&m,&limit);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%I64d",&w[i][j]);
            sum[i][j]=sum[i-1][j]+w[i][j];
        }
}

bool judge(int h)
{
    ll s;
    for(int r=1;r+h-1<=n;r++)
    {
        s=0;
        for(int c=1;c<=h;c++)
            s+=sum[r+h-1][c]-sum[r-1][c];
        if(s<=limit) return 1;
        for(int c=1;c+h<=m;c++)
        {
            s-=sum[r+h-1][c]-sum[r-1][c];
            s+=sum[r+h-1][c+h]-sum[r-1][c+h];
            if(s<=limit) return 1;
        }
    }
    return 0;
}

int solve(int l,int r)
{
    int ans = l;
    while(l<=r)
    {
        int mid = (l+r)/2;
        if(judge(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    return ans*ans;
}

void run()
{
    pre();
    printf("%d\n",solve(0,min(n,m)));
}

int main()
{
    #ifdef LOCAL
    freopen("case.txt","r",stdin);
    #endif
    int _;
    scanf("%d",&_);
    while(_--)
        run();
    return 0;
}

 

推荐阅读