题目背景
农民约翰在一片边长是N (2 <= N <= 250)英里的正方形牧场上放牧他的奶牛。(因为一些原因,他的奶牛只在正方形的牧场上吃草。)遗憾的是,他的奶牛已经毁坏一些土地。( 一些1平方英里的正方形)
题目描述
农民约翰需要统计那些可以放牧奶牛的正方形牧场(至少是2x2的,在这些较大的正方形中没有一个点是被破坏的,也就是说,所有的点都是“1”)。
你的工作要在被供应的数据组里面统计所有不同的正方形放牧区域(>=2x2)的个数。当然,放牧区域可能是重叠。
输入输出格式
输入格式:
第 1 行:N,牧区的边长。
第 2 到 n+1 行:N个没有空格分开的字符。0 表示 "那一个区段被毁坏了";1 表示 " 准备好被吃"。
输出格式:
输出那些存在的正方形的边长和个数,一种一行。
输入输出样例
输入样例#1:
6 101111 001111 111111 001111 101101 111001
输出样例#1:
2 10 3 4 4 1
说明
题目翻译来自NOCOW。
USACO Training Section 3.3
我们用dp[i][j][k]表示,从(i,j)点向往延伸k个单位长度能否构成边长为k的正方形
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<algorithm> 7 #include<cstdlib> 8 using namespace std; 9 const int MAXN=301; 10 void read(int &n) 11 { 12 char c='+';int x=0,flag=1; 13 while(c<'0'||c>'9') 14 {c=getchar();if(c=='-')flag=-1;} 15 while(c>='0'&&c<='9') 16 {x=x*10+c-48;c=getchar();} 17 n=(x*flag); 18 } 19 int n; 20 int a[MAXN][MAXN]; 21 int dp[MAXN][MAXN][MAXN]; 22 int happen[MAXN]; 23 int main() 24 { 25 read(n); 26 for(int i=1;i<=n;i++) 27 { 28 string s; 29 cin>>s; 30 for(int j=0;j<n;j++) 31 { 32 a[i][j+1]=s[j]-'0'; 33 if(a[i][j+1]) 34 dp[i][j+1][1]=1; 35 } 36 } 37 for(int k=1;k<=n;k++) 38 for(int i=1;i<=n;i++) 39 for(int j=1;j<=n;j++) 40 if(dp[i+1][j][k]&&dp[i][j+1][k]&&dp[i+1][j+1][k]) 41 dp[i][j][k+1]=1; 42 for(int i=1;i<=n;i++) 43 for(int j=1;j<=n;j++) 44 for(int k=1;k<=n;k++) 45 if(dp[i][j][k]) 46 happen[k]++; 47 else break; 48 int num=1; 49 while(num++&&happen[num]) 50 printf("%d %d\n",num,happen[num]); 51 return 0; 52 }