0MS 
  G++ 
 
#include <stdio.h> 
 #include <assert.h> 
 #include <string.h> 
 #define BEGIN 'A' 
 int graph[26][26]; 
 int repeaterUsingChannel[26]; 
 int channelUsedInfo[27]; // channel 1 ~ 27 
 int totalChannelNum = 0; 
 void dfs(int begin, int totalNum) { 
// printf("%d %d\n", begin, totalNum); 
if (begin >= totalNum) { // all repeater processed 
return; 
} 
if (!begin) { // first repeater 
repeaterUsingChannel[0] = 1; 
channelUsedInfo[1] = 1; 
  
totalChannelNum += 1; 
// printf("%d %d\n", begin, 1); 
} else { 
int adjacentProcessedRepeaterChannel[27] = {0}; 
for (int i = 0; i < begin; i++) { 
// printf("%d %d %d %d\n", begin, i, graph[begin][i], repeaterUsingChannel[i]); 
if (graph[begin][i] == 1) { //adjacent with repeater i  
adjacentProcessedRepeaterChannel[repeaterUsingChannel[i]] = 1; 
} 
} 
int usableChannel = 0; 
for (int i = 1; i <= 27; i++) { // find first usable channel 
if (!adjacentProcessedRepeaterChannel[i]) { 
usableChannel = i; 
break; 
} 
} 
assert(usableChannel); 
repeaterUsingChannel[begin] = usableChannel; 
if (channelUsedInfo[usableChannel]) // check if has been used by other no-adjacent repeater before 
{ 
} else { 
// printf("%d %d\n", begin, usableChannel); 
totalChannelNum++; 
channelUsedInfo[usableChannel] = 1; 
} 
} 
dfs(begin + 1, totalNum); // process next repeator 
 } 
 void getMinChannelNum(int repeaterNum) { 
// for (int i = 0; i < repeaterNum; i++) { 
// 
for (int j = 0; j < repeaterNum; j++) { 
// 
printf("%d ", graph[i][j]); 
// 
} 
// 
printf("\n"); 
// } 
dfs(0, repeaterNum); 
if (totalChannelNum == 1) { 
printf("1 channel needed.\n"); 
} else { 
printf("%d channels needed.\n", totalChannelNum); 
} 
 } 
 int main() { 
int repeaterNum = 0; 
while(1) { 
scanf("%d", &repeaterNum); 
if (!repeaterNum) { 
return 0; 
} 
totalChannelNum = 0; 
memset(graph, 0, sizeof(graph)); 
memset(repeaterUsingChannel, 0, sizeof(repeaterUsingChannel)); 
memset(channelUsedInfo, 0, sizeof(channelUsedInfo)); 
char repeaterInfo[30]; 
for (int i = 0; i < repeaterNum; i++) { 
scanf("%s", repeaterInfo); 
for (int j = 2; j < strlen(repeaterInfo); j++) { 
graph[i][repeaterInfo[j] - BEGIN] = 1; 
// repeaterInfo[i][repeaterInfo[j] - BEGIN] = 1; 
} 
} 
getMinChannelNum(repeaterNum); 
} 
}算是水题, 没有用到多技巧性的解法,就是经典的状态记录+步进式 搜索树.
不过这一类题一般阐述都是要求最优解,而按照搜索树来一般求出来的就是最优解(因为中间有channel资源重用)
阐述一下流程:
首先因为题目的输入是ABCD...,所以首先要做的就是转化成数字,-'A'即可.
然后就是从A开始遍历每个repeater了(我这里直接用的递归调用,dfs(1) -> dfs(2) -> .. -> dfs(last)),针对每个repeater的相邻repeater使用的channel情况来决定此repeater的channel。
注意的是,在处理第i个repeater时,考虑相邻的repeater时,只考虑之前已经分配过channle即已经处理过的repeater, 1~ i-1,
遍历一遍相邻的已经分配的repeater的channel,搞一个channelMap数组记录都有哪些channel被周边使用,
然后从1开始遍历此channelMap数组,找到的第一个没有周边占用的channel即为此repeater的channel(重用了channel资源,达到最优解)
同时因为题目最后要求输出总共的channel数量,因此还要搞一个全局的channel使用情况数组来记录某个channel是否已经被某个repeater使用了,
如果当前分配给此repeatr的channel之前没有被使用过,那么标记此数组的相应位置,并且使用的channelNum+1。
题目难点就在于每次迭代时,要记录和更新的信息多(这就是空间换时间的副作用),很容易有遗漏.










