Description
小王是D市主管经济的副市长,由于经济发展的需要,要在D市组建一个高新技术开发区,经过研究,规划局在D市的东部划出了一块土地作为开发区选址。这块土地是一块矩形平原,小王准备在上面修建一些建筑。为了规划方便,他将矩形划分成NM格。棘手的是,这块土地有些历史文化遗址散布在某些格子内,这些历史文化遗址是万万不能拆除的,否则将激起民愤,小王深知这一点,因此,他的新建筑在选址时要避开这些格子。
假设新的建筑物有P种规格,每种建筑物都是正方形的,占地为TiTi格 (1<=i<=P)。小王想知道对于每种规格的建筑,有多少种不同的合适选址方案(一种合适的选址方案指的是在该建筑所占的正方形区域内不存在有历史文化遗址的格子)。现在请你来当小王的秘书 帮他完成这个光荣而艰巨的任务。
Input
从文件d.in读入数据,输入文件第一行包含三个数,分别代表N,M,P (1<=N,M<=2000,1<=P<=1000)。随后的n行,每行有m个0或1(1表示该格为空地,0表示该格有历史文化遗址)。接下来的P行每行有一个整数Ti (1
Output
结果输出到文件d.out中,共有P行,每行一个整数,第i行的数代表边长为Ti的建筑物选址方案数。
Sample Input
4 4 2
1011
1111
1110
1110
2
3
Sample Output
5
1
.
.
.
.
.
分析
对于这样一个城市
1011
1111
1110
1110
我们想办法把它处理成
1011
1112
1220
1230
其中每个数字代表以该格为右下角,最多可以达成边长为多少的正方形。然后统计,每种边长都可以由比它大的边长的格子达成。
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m,p,f[2010][2010],b[2010][2010],c[2010][2010],tj[2010],maxx;
int main()
{
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d%d",&n,&m,&p);
for (int i=1;i<=n;i++)
{
char zf[m+3];
scanf("%s",&zf);
for (int j=1;j<=m;j++)
f[i][j]=zf[j-1]-'0';
for (int j=1;j<=m;j++)
if (f[i][j]!=0) b[i][j]=b[i][j-1]+1;
}
for (int j=1;j<=m;j++)
for (int i=1;i<=n;i++)
if (f[i][j]!=0) c[i][j]=c[i-1][j]+1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (f[i][j]!=0)
{
f[i][j]=min(min(f[i-1][j-1]+1,b[i][j]),c[i][j]);
tj[f[i][j]]++;
}
int maxx=max(n,m);
for (int i=maxx-1;i>=1;i--)
tj[i]+=tj[i+1];
for (int i=1;i<=p;i++)
{
int t;
scanf("%d",&t);
printf("%d
",tj[t]);
}
fclose(stdin);
fclose(stdout);
return 0;
}