您的位置:首页 > 其它

zoj 2412 dfs

2013-05-14 11:23 267 查看
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2412

题意:有11种不同的水管,如果它们能连通,则可以流水,求一块地上连通水管数。

思路:这题主要是先要把不同的水管表示出来,一开始觉得要表示出来很麻烦,后面去看了别人写的。地有四个方向,某个方向上有水管则为1,没有为0,这样就表示出来了。然后在搜索过程中,如果当前的地在某个方向i上有水管,则看相邻的地在对应的方向(i+2)%4上有无水管,有的话继续搜下去,没有就不搜咯。其他部分和zoj的1709差不多,用一个visited数组来记录某块地有没有被搜过,0为没被搜,1为被搜过。

#include<cstdio>
#include<cstring>

const int maxn=52;
int map[maxn][maxn];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int type[11][4]={{1,0,0,1},{1,1,0,0},{0,0,1,1},{0,1,1,0},{1,0,1,0},
{0,1,0,1},{1,1,0,1},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,1,1}};//水管类型
int m,n;
int visited[maxn][maxn];

void dfs(int x,int y)
{
visited[x][y]=1;
int xx,yy;
for(int i=0;i<4;i++)
{
if(type[map[x][y]][i]==0) continue;
xx=x+dir[i][0];yy=y+dir[i][1];
if(xx<0 || xx>=m || yy<0 || yy>=n) continue;
if(visited[xx][yy]==1) continue;
if(type[map[xx][yy]][(i+2)%4]==1)
dfs(xx,yy);
}
}
int main()
{
int cnt;
char c;
while(scanf("%d%d",&m,&n) && m>0 && n>0)
{
memset(visited,0,sizeof(visited));
cnt=0;
getchar();
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%c",&c);
map[i][j]=c-'A';//变为数字
}
getchar();
}
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(visited[i][j]==0)
{
dfs(i,j);
cnt++;
}
printf("%d\n",cnt);
}
return 0;
}


在写的过程中老是有些小错误,表示很内伤啊。。。。

下面的代码是用了map来把字母A,B等映射为数字。功能和上面的map[i][j]=c-'A'一样。纯属无聊。

#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int maxn=52;
int s[maxn][maxn];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int type[11][4]={{1,0,0,1},{1,1,0,0},{0,0,1,1},{0,1,1,0},{1,0,1,0},
{0,1,0,1},{1,1,0,1},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,1,1}};//水管类型
map<char,int> ma;
int m,n;
int visited[maxn][maxn];
void dfs(int x,int y)
{
visited[x][y]=1;
int xx,yy;
for(int i=0;i<4;i++)
{
if(type[s[x][y]][i]==0) continue;
xx=x+dir[i][0];yy=y+dir[i][1];
if(xx<0 || xx>=m || yy<0 || yy>=n) continue;
if(visited[xx][yy]==1) continue;
if(type[s[xx][yy]][(i+2)%4]==1)
dfs(xx,yy);
}
}
int main()
{
int cnt;
char c;
for(int i=0;i<11;i++)
{
ma['A'+i]=i;
}
while(scanf("%d%d",&m,&n) && m>0 && n>0)
{
memset(visited,0,sizeof(visited));
cnt=0;
getchar();
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%c",&c);
s[i][j]=ma[c];//变为数字
}
getchar();
}
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(visited[i][j]==0)
{
dfs(i,j);
cnt++;
}
printf("%d\n",cnt);
}
return 0;
}


另外,此题用并查集做也可以。还是要先把11种水管表示出来,然后可以连通的水管就合并在一个集合中,统计各个集合中元素个数,再求和。代码就不写了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: