【DFS + 四色定理】poj 1129 Channel Allocation
题目描述:
http://poj.org/problem?id=1129
中文大意:
当无线电台在非常大的区域上广播时,需要用到中继器,其作用是重新发信号,使得每个接收器都能接收到较强的信号。
相邻的中继器需要使用不同的信道,以此来避免二者之间的相互干扰。
由于射频频谱是一种宝贵的资源,因此中继器网络所需的信道数量越少越好。
要求编写一个程序,确定一个中继器网络所需的最小信道数。
思路:
四色定理的变形:任何一张地图,只用四种颜色就能使具有共同边界的国家着上不同的颜色。
对于每个中继器的信道,都有两种选择:
①使用未被相邻中继器使用的信道。
②使用新的信道。
任选一种,设置为当前中继器的信道,接着设置下一个中继器的信道,以此类推,直至所有中继器的信道设置完毕。
回溯回来时,设置当前中继器的信道为另外一种,继续执行深搜。
注意 channel 的单复数问题。
1 channel needed.
3 channels needed.
代码:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int n;
string maps[26];
int channel[26];//各中继器的信道信息
int min_k;//最小信道数
//index:中断器索引
//k:当前信道个数
void dfs(int index, int k){
//所有中继器设置完成
if(index == n){
if(min_k > k){
min_k = k;
}
return;
}
//四色定理:任何一张地图,只用四种颜色就能使具有共同边界的国家着上不同的颜色
if(k > 4){
return;
}
//检查哪些信道可以使用
bool* used = new bool[k]();
for(int j=0;j<maps[index].size();j++){
//相邻中继器的索引
int beside = maps[index][j] - 'A';
//当前信道已经被使用
if(channel[beside] != -1){
used[channel[beside]] = true;
}
}
//两种选择:
//1.使用未被相邻中继器使用的信道
for(int j=0;j<k;j++){
if(!used[j]){
channel[index] = j;
dfs(index+1, k);
}
}
//2.使用新的信道
channel[index] = k;
dfs(index+1, k+1);
}
int main(){
while(cin>>n && n){
string str;
for(int i=0;i<n;i++){
cin>>str;
int index = str[0] - 'A';
if(str.size() > 2){
maps[index] = str.substr(2);
}
else{
maps[index] = "";
}
}
min_k = 26;
memset(channel, -1, sizeof(channel));
dfs(0, 0);
if(min_k == 1){
printf("%d channel needed.\n", min_k);
}
else{
printf("%d channels needed.\n", min_k);
}
}
}
//一组测试用例:
//10
//A:BCDEFG
//B:ACGH
//C:ABDH
//D:ACEHJ
//E:ADFIJ
//F:AEGI
//G:ABFHI
//H:BCDGIJ
//I:EFGHJ
//J:DEHI