0
点赞
收藏
分享

微信扫一扫

poj-1129

ZSACH 2023-05-23 阅读 89


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。

题目难点就在于每次迭代时,要记录和更新的信息多(这就是空间换时间的副作用),很容易有遗漏.


举报

相关推荐

0 条评论