矩阵
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
有一个二维矩阵,长和宽分别是N,M。矩阵上的每个点有两个状态(0,1),问能不能找到一个K*K的子矩阵,子矩阵里面每个点的状态全为0?
Input
第一行为一个整数T,代表T组数据。(1=<T<=10)
第二行为三个整数N,M,K。(1<=N,M<=1000,1<=K<=min(N,M))
接下来N行,每行有M个整数,代表矩阵上对应的点的状态,状态只有0,1两种。
Output
对于每个测试样例,输出一行,如果能找到子矩阵,输出"Yes",否则输出"No"。每个测试样例占一行。
Sample Input
2
3 3 2
1 0 0
1 0 0
1 1 1
3 3 2
1 0 0
0 1 0
0 0 0
Sample Output
Yes
No
题意就不说了
暴力应该是不行的,若果你枚举这个k*k的矩阵的左边端点,当k=n/2时候 时间复杂度是n^4次方 肯定超时!
比赛的时候总觉得做过这样的问题,但是就是想不起来ヽ(*。>Д<)o゜
随后突然间来了灵感!!!!!!
如果矩阵的每一位置的值代表往下连续为0的个数,也是就是说每一行算是一个柱形图(向下的),那么只要在每一行找到
柱形图的长度>=k的连续的k个即可。
例子:
1 0 0
1 0 0
1 1 1
处理过后就是
0 2 2 第一个0代表往下有0个连续的0,第二个2代表往下有2个连续的0,第三个2代表往下有2个连续的0
0 1 1 第一个0代表往下有0个连续的0,第二个1代表往下有2个连续的0,第三个1代表往下有2个连续的0
0 0 0 向上一下
每一行的值都可代表一个柱形图,其值就代表柱形图的高度,即连续为0个有多少个。
那这道题岂不是简单了O(∩_∩)O!!!!!!
输入的时候把这个矩阵处理一下成柱状图的形式,为了降低时间复杂度,我这里把这个柱形图的方向改为行,即第j列的第i个代表这一行左边来连续的0的个数,然后遍历每一列找出连续k个柱状高度>=k的矩阵即可!
代码:
/*
n^2的方法
按照列数在每一行搞出一个柱形图 代表下面最多有几个连续的0 最后枚举每列只要大于k的数连续出现k次即可
*/
#include<stdio.h>
#include<string>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1010;
int matric[maxn][maxn];
int main()
{
int t,n,m,k;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&m,&k);//n行m列
int cnt=0;
for(int i=1; i<=n; i++)
{
cnt=0;
for(int j=1; j<=m; ++j)
{
scanf("%d",&matric[i][j]);
if(matric[i][j])//即使选连续0的个数
cnt=0;
else
{
cnt++;
}
matric[i][j]=cnt;
}
}//搞出柱形图
int flag=1;
for(int i=m; i>=k&&flag; --i) //枚举列数
{
cnt=0;
for(int j=1; j<=n; ++j)//枚举行数
{
if(matric[j][i]>=k)
cnt++;
else
cnt=0;
if(cnt>=k)
{
flag=0;
break;
}
}
}
if(flag)
printf("No
");
else
printf("Yes
");
}
}