看到这题就想到了USACO3.3 的 home on the range....但这题的数据量更大...用之前的方法显然效率不能满足了...之前用的是优化BFS...这里用的是DP...
思路也很简单...DP的目的无非是要利用前面的结果来直接推出后面的结果而减少甚至排出重复计算与判断...这里用M [ i ] [ j ] 表示 ( i,j ) 点为正方形右下方的点时能得到的最大正方形( ( i,j ) 这个点不是障碍 )...那么M [ i ] [ j ]的值实际上就是 M [ i-1 ][ j-1 ] M [ i-1 ][ j ] M [ i ][ j-1 ] 三个中的最小值+1...试想一下.. 点 ( i-1,j-1 )可得到对 ( i , j ) 左上角这个一块的判断情况...而 M [ i-1 ] [ j ] 能得到对当前点 ( i,j ) 上右一条的判断结果..M [ i ] [ j-1] ] 得到当前点 ( i,j ) 左下一条的判断结果...综合取交集就是 M [ i ][ j ] 能得到的最到正方形边长..
所以如此..从左上角的点顺序判断更新到右下角的点..最复杂的数据也只需要10^6次循环...可以承受...
Program:
/*
ID: zzyzzy12
LANG: C++
TASK: bigbrn
*/
#include<iostream>
#include<istream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stack>
#include<map>
#include<algorithm>
#include<queue>
#define oo 2000000005
#define ll long long
#define pi (atan(2)+atan(0.5))*2
using namespace std;
int m,n,arc[1006][1006];
int ans,M[1006][1006];
int main()
{
freopen("bigbrn.in","r",stdin);
freopen("bigbrn.out","w",stdout);
int i,j;
memset(arc,0,sizeof(arc));
memset(M,0,sizeof(M));
scanf("%d%d",&n,&m);
while (m--)
{
scanf("%d%d",&i,&j);
arc[i][j]=1;
}
ans=0;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (!arc[i][j])
{
M[i][j]=min(M[i-1][j-1],min(M[i][j-1],M[i-1][j]))+1;
if (M[i][j]>ans) ans=M[i][j];
}
printf("%d\n",ans);
return 0;
}