题目描述
由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个 N×M(1≤N≤100,1≤M≤100)N×M(1≤N≤100,1≤M≤100) 的网格图表示。每个网格中有水(W
) 或是旱地(.
)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。
输入第 11 行:两个空格隔开的整数:N 和 M。
第 22 行到第 +1N+1 行:每行 M 个字符,每个字符是 W
或 .
,它们表示网格图中的一排。字符之间没有空格。
输出一行,表示水坑的数量。
输入样例
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
输出样例
3
AC 代码
#include<stdio.h>
#include<string.h>
char field[500][500];
int book[500][500];
int next[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
int count,i,j,n,m;
void dfs(int x,int y){
int tx,ty,k;
for(k=0;k<8;k++){
tx=x+next[k][0];
ty=y+next[k][1];
if(field[tx][ty]=='W' && tx>=0 && tx<n && ty>=0 && ty<m && book[tx][ty]==0 ){
book[tx][ty]=1;
dfs(tx,ty);
}
}
}
int main(){
scanf("%d %d",&n,&m);
for(i=0;i<n;i++){
scanf("%s",field[i]);
}
count=0;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(field[i][j]=='W' && book[i][j]==0){
book[i][j]=1;
dfs(i,j);
count++;
}
}
}
printf("%d",count);
return 0;
}
搞了好久多没有搞出这道题 然后就逃避但是想想还是要做的 于是过了一周又来看 好吧我的效率的确是感人。。。
这是一道dfs搜索题 判断连通块 不需要回溯 一直查找下去就好了 在查找函数中从一个点出发向它的八个方向查找 如果接下来的点是W并且没有被查找过 那么就可以继续查找它的下一个点 查找操作相同 退出函数说明一个连通块已经判断完毕了于是计数器就可以加一
我的问题:1.主函数dfs(i,j)前没有进行标记而是把坐标传过去再进行标记 2.把k定义成全局变量而不是局部变量
这样输入也会出错
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%d",&field[i][j]);
}
}
方向
可以定义成一个二维数组 也可以定义成两个一维数组一个管x一个管y 还可以用双重for循环嵌套
for(i=x-1;i<=x+1;i++){
for(j=y-1;j<=y+1;j++){
标记 搜索
}
}
二维前缀和
给一个数组arr
1 5 6 8
9 6 7 3
5 3 2 4
求这个数组(1,1)到(2,2)的区间和,(0,1)到(1,3)的区间和
二维前缀和数组的定义:sum[i][j]是从(0,0)到(i,j)的和
核心:
sum[i][j]=arr[i][j]+sum[i-1][j]+sum[i][j-1]+sum[i-1][j-1]
原数组这个位置的数+左边一列的+上边一列的+左上一列的
sum{x1,y1}{x2,y2}=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]
(x1,y1)到(x2,y2)的区间和远一点位置的数组减去多余的再加回来多减去的
考虑特殊情况:
当i=0时: sum[0][j]=sum[0][j-1]+arr[0][j]
sum{0,y1}{0,y2}=sum[0][y2]-sum[0][y1-1]
相当于一个一维数组 上面和右上不需要再减去,只要减去左边多余的就好
当j=0时:sum[i][0]=sum[i-1][0]+arr[i][0]
sum{x1,0}{x2,0}=sum[x2][0]-sum[x1-1][0]
当i=0,j=0时:sum{0,0}{0,0}=arr[0][0]
源代码如下:
#include<bits/stdc++.h>
using namespace std;
const int n = 3,m = 4;
int g[n][m] = { {1,5,6,8},
{9,6,7,3},
{5,3,2,4} };
int sum[n][m];
void pre_sum(){
sum[0][0]=g[0][0];
for(int i=1;i<n;i++)
sum[i][0]=sum[i-1][0]+g[i][0]; //第一列
for(int j=1;j<m;j++)
sum[0][j]=sum[0][j-1]+g[0][j]; //第一行
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
sum[i][j]=g[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
}
}
}
int get_sum(int x1,int y1,int x2,int y2){
if(!x1&&!y1) return sum[x2][y2]; //就是从零零开始 左上角为0 0 同定义
if(!x1) return sum[x2][y2]-sum[x2][y1-1];//左上角的行为0 抽象成为多行的一维数组
if(!y1) return sum[x2][y2]-sum[x1-1][y2];//左上角的列为0 抽象成为多列的一维数组
return sum[x2][y2]-sum[x2][y1-1]-sum[x1][y2]+sum[x1-1][y1-1];
}
int main(){
pre_sum();
cout << get_sum(1,1,2,2) << " "<<get_sum(0,1,1,3);
return 0;
}
写的乱七八糟的 还是要是要用做题来检验巩固自己是不是真的弄懂了
然后就是越来越发现自己编程能力跟优秀的人差距越来越大了 希望自己不要懈怠好好努力学知识