zoj 2412 dfs

链接: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种水管表示出来,然后可以连通的水管就合并在一个集合中,统计各个集合中元素个数,再求和。代码就不写了。

原文地址:https://www.cnblogs.com/54zyq/p/3077463.html