1. 程式人生 > >矩陣(01矩陣中找到k*k的全0子矩陣)

矩陣(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");
    }
}