每日三题-Day6-C(CSU 1508 地图的四着色 巧妙剪枝搜索dfs)

1508: 地图的四着色

Submit Page      Summary      Time Limit: 20 Sec       Memory Limit: 128 Mb       Submitted: 222       Solved: 102    

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

思路:

先用dfs,将四连通的相同字母的每一片编号,比如
AABB
BBAA
处理为
0011
2233
然后将每一片编号相同的区域作为一个以这个号码为编号的结点,构建邻接矩阵。
如果一个编号的四连通有其他编号,说明这两个结点连通,邻接。
得到邻接矩阵:
0110
1001
1001
0110
然后用搜索,尝试每一个结点使用每一种颜色(用邻接矩阵判断方案是否可行)

直接搜索会超时,我们尝试剪枝:
男使用AB颜色,女使用CD颜色。
如果我们强制规定,男使用的第一种颜色是A,女使用的第一种颜色是C,那么我们可以得到很大的时间上的优化。
而先使用哪个颜色,都是一样的。所以只需要在这基础上得到的结果乘以4就是最终答案。

AC代码:
#include
#include
#include
#include

using namespace std;
char maps[22][22];
int num[22][22];
int adjMa[33][33];
int color[33];
int ax[5]= {0,0,1,-1};
int ay[5]= {1,-1,0,0};
int r,c;
int n;
void dfs(int a,int b,int p)
{
    num[a][b]=p;
    for(int i=0; i<4; i++)
    {
        int x=a+ax[i];
        int y=b+ay[i];
        if(x>=0&&x=0&&y=0&&x=0&&y

每日三题-Day6-C(CSU 1508 地图的四着色 巧妙剪枝搜索dfs)_第1张图片

你可能感兴趣的:(DFS,每日三题)