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

  • 相关阅读:
    最小生成树计数
    Tree
    NOJ 成绩排名
    NOJ 成绩排名
    NOJ 成绩排名
    NOJ 成绩排名
    NOJ Physics
    NOJ Physics
    NOJ Physics
    NOJ Physics
  • 原文地址:https://www.cnblogs.com/54zyq/p/3077463.html
Copyright © 2011-2022 走看看