二维dp,定义G[i][j]表示i,j为顶点的最大正方形边长.如果G[i][j]本身为1,则转移方程为:G[i][j]=min(G[i+1][j],G[i][j+1],G[i+1][j+1])+1.其实就是由其下方,右方,右下方的点确定它所能构成的最大正方形(在图上可以很清楚的发现这一点).
其实这道题也可以暴力枚举;我们枚举每个点作为正方形左上角顶点时可以得到的最大边长正方形,而边长为k的正方形和k+1的正方形之间是存在关系的.
代码如下:
/*
ID: 15674811
LANG: C++
TASK: range
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define maxn 300
int G[maxn][maxn];
int cnt[maxn];
int main()
{
//freopen("in.txt","r",stdin);
freopen("range.in","r",stdin);
freopen("range.out","w",stdout);
int n;
while(scanf("%d",&n)!=EOF)
{
memset(cnt,0,sizeof(cnt));
memset(G,0,sizeof(G));
for(int i=1;i<=n;i++)
{
char str[maxn];
scanf("%s",str+1);
for(int j=1;j<=n;j++)
G[i][j]=str[j]-‘0‘;
}
for(int i=n;i>=1;i--)
for(int j=n;j>=1;j--)
if(G[i][j])
G[i][j]=min(G[i+1][j],min(G[i][j+1],G[i+1][j+1]))+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
while(G[i][j]>=2)
{
cnt[G[i][j]]++;
G[i][j]--;
}
for(int i=2;i<=n;i++)
if(cnt[i])
printf("%d %d\n",i,cnt[i]);
}
return 0;
}
USACO--3.3Home on the Range+DP
原文地址:http://blog.csdn.net/acm_lkl/article/details/46242855