2023/4/3+4/4总结

题目描述

由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个 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;
}
                
写的乱七八糟的 还是要是要用做题来检验巩固自己是不是真的弄懂了

然后就是越来越发现自己编程能力跟优秀的人差距越来越大了 希望自己不要懈怠好好努力学知识    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值