洛谷P1767 家族_NOI导刊2010普及(10)

来源:互联网 发布:淘宝全网举报入口 编辑:程序博客网 时间:2024/06/05 16:12

题目描述

在一个与世隔绝的岛屿上,有一个有趣的现象:同一个家族的人家总是相邻的(这里的相邻是指东南西北四个方向),不同的家族之间总会有河流或是山丘隔绝,但同一个家族的人不一定有相同姓氏。现在给你岛上的地图,求出岛上有多少个不同的家族。岛上的地图有n行,每行有若干列,每个格子中要么是“ ”,表示大海,要么是“*”,表示河流或山丘,要么是小写字母,表示一户人家的姓氏。

输入输出格式
输入格式:

第一行是个数字N,表示下面信息的行数。接下来是N行字符,每行由小写字母和*号组成,有些行的最前面也可能包含若干连续的空格,表示这些区域是大海,每一行最多不超过200个字符。

输出格式:

一个数字,表示家族数。

输入输出样例
输入样例#1:

4
*zlw**pxh
l*zlwk*hx*
w*tyy**yyy
zzl

输出样例#1:

3

说明

10%的数据,n≤1
30%的数据,n≤10
100%的数据,n≤100每一行最多不超过200个字符。

_NOI导刊2010普及(10)


这道题本身就是一个普通的搜索题(用DFS和BFS都可以,我这里用的是DFS)

然而,关键的考察点在与字符串的读入和边界的处理

对于这道题目来说我个人觉得最好的方式应该是用getline+string的读入

如下

string ch[110]getline(cin,ch[0]);for(int i=0;i<n;i++)    getline(cin,ch[i]);

这样可以便于我们找到ch[i].size()以及接下来的操作

我们将每一个小写的字母存入我们的表中,这样省去了我们在搜索过程中对是否是字符的判别。

   for(int j=0;j<(int)(ch[i].size());j++)     if(ch[i][j]>='a'&&ch[i][j]<='z')       f[i][j]=1;

同时,我们可以将路径记录在当中,省去部分的空间。这非常的重要,如果没有这条就会WA。

在DFS的时候我们考虑一下几点
1.对于每个x来说x>=0x<n即是合法的
2.对于每个y来说y>=0y<lx即是合法的因为在lx以外的地方是不存在新的字母的

接下来就是普通的DFS了

const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};void dfs(int x,int y){    for(int i=0;i<4;i++){        int nx=x+dx[i],ny=y+dy[i];        if(nx>=0 && nx<n && ny>=0 && ny<(int)(ch[nx].size()) && f[nx][ny] ){            f[nx][ny]=0;//记录路径            dfs(nx,ny);        }    }    return ;}

标程如下:

#include <bits/stdc++.h>using namespace std;const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};int n,m,f[111][211],Max,ans;string ch[111];void dfs(int x,int y){    for(int i=0;i<4;i++){        int nx=x+dx[i],ny=y+dy[i];        if(nx>=0 && nx<n && ny>=0 && ny<(int)(ch[nx].size()) && f[nx][ny] ){            f[nx][ny]=0;            dfs(nx,ny);        }    }    return ;}int main(){    cin>>n;getline(cin,ch[0]);    for(int i=0;i<n;i++){        getline(cin,ch[i]);        for(int j=0;j<(int)(ch[i].size());j++)         if(ch[i][j]>='a'&&ch[i][j]<='z')           f[i][j]=1;    }    for(int i=0;i<n;i++)     for(int j=0;j<(int)(ch[i].size());j++)       if(f[i][j])            f[i][j]=0,dfs(i,j),ans++;    cout<<ans<<endl;    return 0;}
原创粉丝点击