题目:Largest Allowed Area
数据:
2
10 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
20 10
1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0
题意:本题的题意就是给你一个矩阵,只包含0或者1,然后让你求出最多只包含一个1的矩阵最大有多大。
思路:一开始看到这道题之后,感觉像搜索问题仔细寻思了一下发现不是,然后就想到了二维前缀和,求出二维前缀和之后,遍历所有的点,以(i, j)为正方形的右下角去二分查找,最大正方形的边长,然后找到最大的边长。但是这道题会卡你的数据,所以需要快速读入。
二维前缀和推荐博客:前缀和差分
视频讲解:https://www.bilibili.com/video/av41245560?from=search&seid=4311438322537468069
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int a[maxn][maxn], sum[maxn][maxn];
int n, m;
bool read(int &num)//快速读入
{
char in;
bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-')
{
IsN=true;
num=0;
}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
{
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
int Judge(int i, int j, int d)//二分查找
{
int l = 1, r = d, mid, ans = 1;
while(l <= r)
{
int mid = (l + r)/ 2;
if (sum[i][j]-sum[i-mid][j]-sum[i][j-mid]+sum[i-mid][j-mid] <= 1)//注意题意最多一个
{
l = mid+1;
ans = mid;
}
else r = mid - 1;
}
return ans;
}
int main()
{
int T;
read(T);
while(T--)
{
read(n);
read(m);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
read(a[i][j]);
sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
}
int ans = 0;
for(int i = 1; i <= n; i++)//遍历所有的点
{
for(int j = 1; j <= m; j++)
{
int d = min(i, j);//以(i, j)为右下角的正方形的边长最大为d
int t = Judge(i, j, d);//
ans = max(ans, t);
}
}
printf("%d\n", ans);
}
return 0;
}