矩陣(01矩陣中找到k*k的全0子矩陣)
矩陣
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\n");
else
printf("Yes\n");
}
}