问题 E: 填色问题 (color)

时间限制: 1 Sec 内存限制: 128 MB

题目描述
有形如下列图形的地图,图中每一块区域代表一个省份,现请你用红(1)、蓝(2)、黄(3)、绿(4)四种颜色给这些省份填上颜色,要求每一省份用一种颜色,且任意两个相邻省份的颜色不能相同,请给出符合条件的填色方案总数。地图用无向图的形式给出,每个省份代表图上的一个顶点,边代表两个省份是相邻的。
输入
有若干行,第一行包含一个自然数n,代表地图上省份数。接下来的n行,每行有n个用空格隔开的0或1,用来描述各省份之间的相邻关系(0表示不相邻,1表示相邻)。
输出
输出数据仅一数,表示符合条件的填色方案总数。
样例输入
5
0 1 1 0 0
1 0 0 0 1
1 0 0 1 1
0 0 1 0 1
0 1 1 1 0
样例输出
168
提示:
对于所有数据,1≤n≤10。

这道题是比较经典的“四色定理”。
首先,四色定理就是无论多么错杂的地图,只须要用四种色彩就能将它区分隔来,这四种颜色可以使相邻的面颜色都不相同。这是1852年英国人弗朗西斯提出来的。直到1976年,美国数学家阿佩尔和哈肯哄骗高速策画机,历时1200小时,成功的证了然四色题目的正确性。
当然了,我也是最近才听说有这个定理的存在,卑微QAQ
思路其实这个题目提示我们了,就是用一个二维数组就可以来代表各个地区之间的关系,1表示相邻,0表示相邻,而且聪明的你一定发现了这个矩阵是个对称矩阵哦 ,因为a[i][j] 和 a[j][i] 都表示的是i和j的相邻关系。
答题思路:
1.先把第一个地区涂成第一个颜色;
2.再把第x个地区涂成color颜色,color从1开始,判断是否满足条件,当与(1,x)之间的区间相邻且颜色相同时,方案不成立,跳出循环。如果满足条件,就对下一个地区填色。

#include <bits/stdc++.h>
#define ll long long
//#define local
using namespace std;
const int N = 15;
const int inf = 0x3f3f3f3f;//1061109567
int n,a[N][N],ans=0,col[N]={0};//a表示相邻关系,col表示每个地区的颜色
void fun(int x)
{
    if(x>n) ans++;//一种填色方案完成
    else
    {
        for(int color=1;color<=4;color++)
        {
            int flag=1;
            for(int num=1;num<x;num++)
            {
                if(a[x][num]&&col[num]==color)//这个算是核心1了。
                {
                    flag=0;
                    break;
                }
            }
            if(flag)//现在填色方案可以满足,进行下一个地区的涂色,并将这个地区重新置为“空白”
                col[x]=color,fun(x+1),col[x]=0;//这个算是核心2了。
        }
    }
}
int main()
{
#ifdef local
    freopen("input.txt","r",stdin);
#endif // local
    scanf("%d",&n);
    memset(col,0,sizeof(col));
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
            scanf("%d",&a[i][j]);
    }
    fun(1);
    printf("%d\n",ans);
    return 0;
}

参考:
https://blog.csdn.net/very_caiing/article/details/7878171?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-4

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值