题意:在广播时,相邻的中继器会互相干扰,为了避免干扰,可以让中继器使用不同的通道。现在给出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;
}