FZU2056 最大正方形(二分答案)

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;
}
时间: 2024-11-09 03:47:27

FZU2056 最大正方形(二分答案)的相关文章

BZOJ 1052 HAOI2007 覆盖问题 二分答案+DFS

题目大意:给定n个点,用三个边长相同的正方形覆盖所有点,要求正方形边界与坐标轴垂直,求正方形边长的最小值 最大值最小,很明显二分答案 但是验证是个问题 考虑只有三个正方形,故用一个最小矩形覆盖这三个正方形时至少有一个在角上 若有四个正方形该结论不成立 于是我们采用DFS的方式 每次用一个最小的矩形覆盖所有的点,枚举矩形的四个角 将正方形填进去 由于最大深度是3,所以时间上完全可以承受 #include<cstdio> #include<cstring> #include<io

bzoj1052 覆盖问题 二分答案 dfs

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1052 题意:找到一个最小边长,使得以此为边长$3$个正方形可以覆盖平面上给定的一些点. 华丽爆零-- 首先看到最小果断想二分答案-- 然后我们证明一个东西-- 首先,根据鸽巢原理,$3$个正方形覆盖由所有点构成的最小矩形一定有一个正方形是压着至少两条边的-- 然后不外乎两种情况-- 1.压的是对边,那么每个都在压对边,有一个正方形会压到三条边,就会压到一个角-- 2.压的是邻边,一定会压到一

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

HDU3081Marriage Match II(二分答案+并查集+最大流SAP)经典

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2507    Accepted Submission(s): 856 Problem Description Presumably, you all have known the question of stable marriage match. A

Codeforce 371C Hamburgers (二分答案)

题目链接 Hamburgers 二分答案,贪心判断即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define LL long long 7 8 char str[1010]; 9 LL len; 10 LL b, c, s, nb, nc, ns, pb, pc, ps; 11 LL money; 12 13 bool

POJ 3080 Blue Jeans(后缀数组+二分答案)

[题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通过拼接符拼成一个串,做一遍后缀数组,二分答案,对于二分所得值,将h数组大于这个值的相邻元素分为一组,判断组内元素是否覆盖全字典,是则答案成立,对于答案扫描sa,输出第一个扫描到的子串即可. [代码] #include <cstdio> #include <cstring> #inclu

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) 二分答案 + 网络流

这道题的意思是给你一个有向图, 每条边上有一个最大载重量, 现在有x头牛要从顶点1走向顶点n, 每头牛要载的重量都是一样的, 问你最多能载多少的重量? 可以二分答案, 算出每头牛的载重, 然后修改边权, 跑一次最大流即可判断当前答案是否正确, 二分答案即可, 注意由于原始边权/每头牛的载重量可能会很大, 因此我们在修改边权时应该注意这一点,将边权的最大值控制在1000000之内, 防止溢出, 代码如下: #include <bits/stdc++.h> using namespace std;

BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连一条流量为k的边.两个人若互相喜欢则点1之间连边,不喜欢则点2之间连边 对于每个要验证的x值 将每个人的点1向源或汇连一条流量为x的边 然后二分答案跑最大流就可以 #include<cstdio> #include<cstring> #include<iostream> #