农田个数
题目描述
你的老家在农村。过年时,你回老家去拜年。你家有一片N×MN×M农田,将其看成一个N×MN×M的方格矩阵,有些方格是一片水域。你的农村伯伯听说你是学计算机的,给你出了一道题: 他问你:这片农田总共包含了多少个不存在水域的正方形农田。
两个正方形农田不同必须至少包含下面的两个条件中的一条:
1.边长不相等
2.左上角的方格不是同一方格
输入格式
输入数据第一行为两个由空格分开的正整数N、M(1<=m< n <=1000)
第2行到第N+1行每行有M个数字(0或1),描述了这一片农田。0表示这个方格为水域,否则为农田(注意:数字之间没有空格,而且每行不会出现空格)
输出格式
满足条件的正方形农田个数。
样例数据
input
3 3
110
110
000
output
5
样例解释
边长为1的正方形农田有4块 边长为2的正方形农田有1块,合起来就是5块
`数据规模与约定
时间限制:1s1s
空间限制:256MB256MB
。其实我现在主要是来倾诉写完这道题的心酸的。
今天下午老师是讲过这道题的,当时听起来的时候感觉蛮简单。代码也不长,最后AC的代码才37行。(还有三行废话)
。可是我写了好久。
首先样例太水了。
样例的图很容易画(毕竟只有 3*3 )。蓝色代表水塘,黄色代表农田。而那些绿的只是代表坐标用的。
方格里的数代表以这个位置为右下角的正方形数有多少。等推完了以后再将整个 f[i][j] 数组加起来。
然后看样例的(2,2)中 f[2][2] 的值来自 f[1][1]+1
但之所以会+1是因为 a[1][2] (a数组存储是水塘还是农田)为 1 ( 农田) 且 a[2][1] 也是 1 (农田)。
所以搜索顺序是一行行,我就先判断a[2-1][2] 或 a[2][2-1] 是否满足条件,若满足,f[2][2] 中的值就是 f[2-1][2-1]+1
若是之前那个数为2,那就不只要判断 f[i-1][j] f[i][j-1] 的条件了,还要判断 f[i-2][j] f[i][j-2] 所以到底要判断到哪里还是要计算一下的。 我是这样算的:
if(a[i][j]=='1') f[i][j]=1;//自己不是水塘,但左上角是水塘
if(a[i][j]=='1'&&a[i-1][j-1]!=0)//自己不是水塘,且左上角有农田
{
int check=1;//检验是否都是农田
for(int k=1;k<=f[i-1][j-1];k++)
{
if(a[i-k][j]=='0') check=0;
if(a[i][j-k]=='0') check=0;
}
if(check==1) f[i][j]=f[i-1][j-1]+1;
}
然后写完程序我去提交了,只得了20!
哎呀我的妈,数据很大,最小的也只有50*50
这。。我本来还想把数据拿来打个表的,这也太大了,要我怎么画图啊。
我只能去拷贝了一下别人的程序,进行打表找不同。经过千辛万苦,跨过山和大海啊,我终于找到了不同。
用的数据是这么一组
9 8
00111001
10010111
01010101
00111111
00111111
00111111
01011011
01000001
01001110
正确的表:
0 0 1 1 1 0 0 1
1 0 0 1 0 1 1 1
0 1 0 1 0 1 0 1
0 0 1 1 1 1 1 1
0 0 1 2 2 2 2 2
0 0 1 2 3 3 3 3
0 1 0 1 2 0 1 2
0 1 0 0 0 0 0 1
0 1 0 0 1 1 1 0
然后我打出来的表:
0 0 1 1 1 0 0 1
1 0 0 1 0 1 1 1
0 1 0 1 0 1 0 1
0 0 1 1 1 1 1 1
0 0 1 2 2 2 2 2
0 0 1 2 3 3 3 3
0 1 0 1 1 0 1 1
0 1 0 0 0 0 0 1
0 1 0 0 1 1 1 0
然后我又绘了一张图:
然后我找到了原因。列如位置**(8,7)**,按照我原先的思路,那里应该是 1 而现实是 2 。
因为虽然 f[8-3][8]!=0 ,还是有两个正方形的。我修改了1个半小时的程序,才改好。
不要问我为什么改这么久。我。。。渣。。一直理不清思路,搞清思路后没多久就写完了代码。
好了,最后是AC的代码
/*天灵灵!地灵灵!让我过吧!我做了几个小时了!*/
#include<bits/stdc++.h>
using namespace std;
char a[5000][5000]={};
int f[5000][5000]={};
int N,M;
int tmp=0;
int main()
{
// freopen("count.in","r",stdin);
// freopen("count.out","w",stdout);
cin>>N>>M;
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++)
cin>>a[i][j];
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++)
{
if(a[i][j]=='0') f[i][j]=0;//自己本身就是水塘
if(a[i][j]=='1')//自己不是水塘
{
int tmp=0;
for(int k=1;k<=f[i-1][j-1]+1;k++)
{
tmp++;
if(a[i-k][j]=='0') break;
if(a[i][j-k]=='0') break;
}
f[i][j]=tmp;
}
tmp=tmp+f[i][j];//相加
}
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
cout<<tmp<<endl;
return 0;
}
2019-03-19 21:12