POJ 1129 Channel Allocation dfs(四色定理)

题意:在广播时,相邻的中继器会互相干扰,为了避免干扰,可以让中继器使用不同的通道。现在给出n个中继器,以及分别与它们相邻的中继器。求最少需要的通道数。
题解:给出两组代码,第二组用到了四色定理。

四色定理(Four color theorem)最先是由一位叫古德里(Francis Guthrie)的英国大学生提出来的。四色问题的内容是:“任何一张地图只用四种颜色就能使具有共
边界的国家着上不同的颜色。”用数学语言表示,即“将平面任意地细分为不相重叠的区域,每一个区域总可以用1,2,3,4这四个数字之一来标记,而不会使相邻的两个区域得到相同的数字。”这里所指的相邻区域,是指有一整段边界是公共的。如果两个区域只相遇于一点或有限多点,就不叫相邻的。因为用相同的颜色给它们着色不会引起混淆。

#include <iostream>
using namespace std;

char str[30];
bool map[30][30];
int chan[30];
int n,res;

bool isLeagal( int nth, int id  )
{
	for ( int i = 1; i < nth; i++ )  //若中继器 i 与中继器 nth 有关联且通道id已经被使用,则不可行。
		if ( map[i][nth] && chan[i] == id ) 
			return false;
    return true;
}

void dfs( int nth, int mini )  // mini带代表了通道的个数,编号1,2,3,4... 若通道N被使用,则说明至少需要N个通道。
{
	if ( nth > n )
	{
		if ( mini < res )
			res = mini;
		return;
	}

	for ( int i = 1; i <= mini; i++ )
	{
		if ( isLeagal(nth,i) )       // 不增加通道个数,即在编号1...mini的通道中为第nth个中继器选择通道
		{
			chan[nth] = i;
			dfs(nth+1,mini);
		}
	}

	chan[nth] = mini+1;   // 选择第nth个中继器的通道为编号mini+1的通道
	dfs(nth+1,mini+1);
}

int main()
{
	while ( cin >> n && n )
	{
		memset(map,0,sizeof(map));
		memset(chan,0,sizeof(chan));
		for ( int i = 1; i <= n; i++ )
		{
			cin >> str;
			for ( int j = 2; str[j]; j++ )
				map[str[0]-'A'+1][str[j]-'A'+1] = map[str[j]-'A'+1][str[0]-'A'+1] =  true;
		}

		res = 30;
		dfs(1,0);  
		if ( res == 1 )
			cout << res << " channel needed." << endl;
		else
			cout << res << " channels needed." << endl;
	}
	return 0;
}

四色定理解法
#include <iostream>
using namespace std;
char str[30];
int map[30][30];
int color[30];
int n;

bool isLegal ( int x, int temp )
{
	for ( int i = 1; i < x; i++ )
		if ( map[i][x] && color[i] == temp )
			return false;
		return true;
}

bool dfs ( int x, int c )
{
	if ( x > n )
		return true;
	for ( int i = 1; i <= c; i++ )
	{
		if ( isLegal(x,i) )
		{
			color[x] = i;
			if ( dfs(x+1,c) )
				return true;
		}
	}
	return false; 
}


int main()
{
	while ( cin >> n && n )
	{
		int i,j;
		memset(map,0,sizeof(map));
		for ( i = 1; i <= n; i++ )
		{
			cin >> str;
			for ( j = 2; str[j]; j++ )
				map[str[0]-'A'+1][str[j]-'A'+1] = map[str[j]-'A'+1][str[0]-'A'+1] =  true;
		}
		for ( i = 1; i <= 4; i++ ) /* 分别判断用 1个, 2个, 3个, 4个通道能否实现要求 */
		{
			if ( dfs(1,i) )
				break;
		}
		if ( i == 1 )
			cout << i << " channel needed." << endl;
		else
			cout << i << " channels needed." << endl;
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值