Time Limit: 1000 MS Memory Limit: 131072 K
Description
Long time ago, a king occupied a vast territory. Now there is a problem that he worried that he want to choose a largest square of his territory to build a palace. Can you help him? For simplicity, we use a matrix to represent the territory as follows: 0 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 0 0 0 1 0 0 Every single number in the matrix represents a piece of land, which is a 1*1 square 1 represents that this land has been occupied 0 represents not Obviously the side-length of the largest square is 2![]()
Input
The first line of the input contains a single integer t (1≤t≤5) — the number of cases. For each case The first line has two integers N and M representing the length and width of the matrix Then M lines follows to describe the matrix 1≤N,M≤1000Output
For each case output the the side-length of the largest squareSample Input
2 5 5 0 0 0 0 0 0 1 0 1 0 1 1 0 1 0 0 1 1 0 0 0 0 1 0 0 5 5 0 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 0 0 0 1 0 0Sample Output
1 2
我主要讲两种方法!主要是动规!
这道题改变了我对动规狭隘的看法,原来我以为动规一般都是用一维数组做的
这种图的问题应该是搜索!于是我在搜索上浪费了很长时间!
下面说一下动规思路!
1.因为找的是正方形!所以,在正方形的一点一定最少有3个相邻小正方形为1
如点 2 2 如果说2 2 是一个正方形的一部分,那么就可能有1 1 , 1 2 ,2 1 这3个点为1
所以,我们找包括 2 2 在内的4个点的最小值加1,即为能组成的最大的正方形!
如样例二
转化一下就为
0 0 0 0 0
0 1 0 1 0
1 1 1 1 0
0 1 2 0 0
0 0 1 0 0
然后找出最大的值!就OK
#include<stdio.h>
#include<string.h>
#define inf 99999999
int map[1005][1005];
int dp[1005];
int dir[3][2]={{-1,-1},{-1,0},{0,-1}};
int max(int a,int b)//找出4个点的最小值,然后返回最小值加一
{
int min=inf;
for(int i=0;i<3;i++)
{
int dx=a+dir[i][0];
int dy=b+dir[i][1];
if(map[dx][dy]<min)
{
min=map[dx][dy];
}
}
return min+1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b,num=0;
scanf("%d%d",&a,&b);
memset(map,0,sizeof(map));
for(int i=1;i<=a;i++)
{
for(int j=1;j<=b;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==1)
{
map[i][j]=max(i,j);
if(map[i][j]>num)//直接找处理后的最大值!少点for循环
{
num=map[i][j];
}
}
}
}
printf("%d\n",num);
}
}
第二种方法
也是先预处理,如果一个点(不为0)的前一个点也不为0,那么这个数就是上个数+1
比如样例2预处理完是这样
0 0 0 0 0
0 1 0 1 0
1 2 3 4 0
0 1 2 0 0
0 0 1 0 0
然后我每一数列找能凑成的最大正方形
比如第三列 0 0 3 2 1
我for循环一下,找到第一个不为0的数3时,向后搜,如果后面的数小于这个数(2<3)那么停止搜,更新一下从2开始搜,发现1<2,停止更新,从1开始搜
最后结果是最大正方形边长为1!!!!不对,其实少了一步
我们要倒过来再搜一遍,从1搜,1直接组成一个正方形,好了搜2,搜到3发现可以凑成2*2方形,从3开始搜,发现后面的都不行!
就这样,每列都搜一遍,就过了
代码就不上了!