• 寒假Day31:CSU1508地图的四着色bfs+dfs


    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1508

    Description:

    有一个R行C列的网格地图,每个国家是一个四连通区域。你的任务是用红,绿,蓝,黄四种颜色给地图着色,使得相邻国家的颜色不同。
    一个人着色比较无趣,所以你想请女朋友陪你一起涂——你涂红绿,她涂蓝黄。当然,绅士是不会让让女朋友受累的,所以她最多只需涂5个国家(恰好5个也行)。
    你的任务是统计有多少种着色的方法。注意,每个颜色都至少要用一次。

    Input

    输入包含不超过100组数据。每组数据第一行为两个整数R和C (1<=R,C<=20),即网格的行数和列数。以下R行每行C个大写字母。相同字母所组成的四连通区域代表一个国家。输入保证国家数目不超过30,并且大多数测试点的国家数都比较小。

    Output

    对于每组数据,输出测试点编号和着色方案数。

    Sample Input

    2 4
    AABB
    BBAA
    1 5
    ABABA
    4 7
    AABAABB
    ABBCCCB
    BBAACBB
    CCABBAC

    Sample Output

    Case 1: 24
    Case 2: 144
    Case 3: 3776

    Hint

    Source  湖南省第十届大学生计算机程序设计竞赛

     

    思路:

    1、

    先用bfs1给每一点进行标号,用第一组样例来说

    AABB

    BBAA,

    标完号之后就变成了

    1122

    3344

    2、

    用bfs2把相邻的国家连接起来,用邻接表存储,vector可以勉强水过

    用上面那组例子,连接好之后就变成

    1-2-3

    2-1-4

    3-1-4

    3、

    每一种可行情况ans++,最后的结果*4不会超时,因为有四种可能,AC、AD、BC、BD,男生先染、女生后染。

    邻接表过的,很多处理细节需要注意,还得一遍遍尝试。

    AC代码:

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    char a[25][25];
    int n,m,num,tot,ans;
    bool book1[35][35],book2[35][35];
    int id[25][25],head[35],color[35];
    int to[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
    
    struct node
    {
        int x,y;
    } p,q;
    
    struct E
    {
        int v,nextt;
    } e[1005];
    
    void add(int u,int v)
    {
        e[tot].v=v;
        e[tot].nextt=head[u];
        head[u]=tot++;
    }
    
    void bfs1(int x,int y)
    {
        id[x][y]=num;//横纵坐标
        p.x=x;
        p.y=y;
        queue<node>Q;
        Q.push(p);
        while(!Q.empty())
        {
            q=Q.front();
            Q.pop();
            for(int i=0; i<4; i++)
            {
                p=q;
                p.x+=to[i][0];
                p.y+=to[i][1];
                if(p.x>=0&&p.x<n&&p.y>=0&&p.y<m&&a[p.x][p.y]==a[q.x][q.y]&&id[p.x][p.y]==0)
                {
                    id[p.x][p.y]=num;
                    Q.push(p);
                }
            }
        }
    }
    
    void bfs2(int x,int y)
    {
        queue<node>Q;
        p.x=x;
        p.y=y;
        Q.push(p);
        while(!Q.empty())
        {
            q=Q.front();
            Q.pop();
            book1[q.x][q.y]=1;
            for(int i=0; i<4; i++)
            {
                p=q;
                p.x+=to[i][0];
                p.y+=to[i][1];
                //if(p.x>=0&&p.x<n&&p.y>=0&&p.y<m&&book1[p.x][p.y]==0)
                if(p.x>=0&&p.x<n&&p.y>=0&&p.y<m)
                {
                    if(id[p.x][p.y]!=id[q.x][q.y])
                    {
                        //add(id[p.x][p.y],id[q.x][q.y]);
                        //add(id[q.x][q.y],id[p.x][p.y]);
                        book2[id[p.x][p.y]][id[q.x][q.y]]=1;
                        book2[id[q.x][q.y]][id[p.x][p.y]]=1;
                        continue;
                        //  Q.push(p);
                    }
                    if(book1[p.x][p.y]==0)
                        Q.push(p);//MLE
                }
    //            if(book1[p.x][p.y]==0)
    //            Q.push(p);//MLE
            }
        }
    }
    
    int check(int s,int k)
    {
        //不能传入i、k
        for(int i=head[s]; i!=-1; i=e[i].nextt)
        {
            if(color[e[i].v]==k)
                return 0;
        }
        return 1;
    }
    
    void dfs(int i,int a1,int a2,int a3,int a4)//涂到第几个城市,四种颜色分别涂了几个
    {
        if(num+1==i)
        {
            if(a1&&a2&&a3&&a4)
                ans++;
            return ;
        }//只能写成这样,改了一下要么RT要么WA
    
        color[i]=0;
        if(check(i,0))
            dfs(i+1,a1+1,a2,a3,a4);//第一种颜色
        
        color[i]=1;
        if(a1&&check(i,1))
            dfs(i+1,a1,a2+1,a3,a4);//
        
        color[i]=2;
        if(a3+a4<5&&check(i,2))
            dfs(i+1,a1,a2,a3+1,a4);//
            
        color[i]=3;
        if(a3&&a3+a4<5&&check(i,3))
            dfs(i+1,a1,a2,a3,a4+1);//
    }
    
    int main()
    {
        int t=1;
        while(~scanf("%d %d",&n,&m))
        {
            memset(id,0,sizeof(id));
            memset(book1,0,sizeof(book1));
            memset(book2,0,sizeof(book2));
            memset(head,-1,sizeof(head));
            for(int i=0; i<n; i++)
                scanf("%s",a[i]);//注意一下
            num=0;
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                {
                    if(id[i][j]==0)
                    {
                        num++;
                        bfs1(i,j);
                    }
                }
            }//vs bfs1(0,0)
    
            tot=0;
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                {
                    if(book1[i][j]==0)
                        bfs2(i,j);
                }
            }
    
    
    //        for(int i=0; i<n; i++)
    //        {
    //            for(int j=0; j<m; j++)
    //            {
    //                if(book[i][j]==0)
    //                    bfs2(i,j);
    //            }
    //        }
            for(int i=1; i<=num; i++)
            {
                for(int j=1; j<i; j++)//到n也WA
                {
                    if(book2[i][j]==1)
                        add(i,j);
                }
            }
            ans=0;
            dfs(1,0,0,0,0);
            printf("Case %d: %d\n",t++,ans*4);
        }
        return 0;
    }

    Thinking

    反正这题一点也不好写,稍微改改就要错,提交了二十几,写完我就看英语去~~~

    我觉得难的题我过了也没啥用,

    最近天天凌晨睡觉,一个代码扣几个小时,即使再写也不一定能过,

    感觉还是只能做简单题,

    我还是去刷cf的简单题叭~~~

    再这样下去,一事无成,时间也耗在着,几个小时做一道题,好几天都这样,又和以前一样了~

    还是要加油鸭

  • 相关阅读:
    我的php学习笔记(三十六)PHP中开发自己的UBB代码
    Eclipse和MyEclipse安装和使用git(egit)图解笔记
    在ECSHOP首页增加一个浏览排行
    计算机网络
    游戏系统开发笔记(四)——游戏程序简介
    【自考】操作系统概论
    ZOJ 3700 Ever Dream 文章中单词的处理
    【自考】计算机网络技术
    Lvm 折腾小记
    UbuntuKylin的美好前景
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12321520.html
Copyright © 2020-2023  润新知