ZOJ 1084 Channel Allocation 四色定理

来源:互联网 发布:java主要用途 编辑:程序博客网 时间:2024/05/01 22:23

这个题真难啊, AC率42%

这题用到了“四色定理” : 任何一张地图只用四种颜色就能使具有共同边界的国家着上不同的颜色。这里所指的相邻区域,是指有一整段边界是公共的。如果两个区域只相遇于一点或有限多点,就不叫相邻的。因为用相同的颜色给它们着色不会引起混淆。

我做了好几遍, 错了好几遍, 后来看了别人的代码, 勉强懂了, 但是还有挺多细节不懂,

我发现好多人发表的日志都差不多的代码,应该也看了别人的代码, 也不知道他们是否真的懂了。我把我理解的注释清楚点, 希望如果要是你看懂了, 能帮我解决疑问, 代码可以AC

#include "iostream"#include "cstdio"#include "cstring"using namespace std;int graph[30][30];int used[30];int n;//此函数检验从node到结束, 在只有color中颜色下可否全填。bool dfs(int node, int color){int i, j, flage;for(i = 0; i < color; i++){used[node] = i;//给node涂色    flage = 1;for(j = 0; j < node; j++){//对在node之前的节点进行检测if(graph[j][node] && used[j] == used[node]){//如果节点j与node有关联,而且颜色相同, 可换种颜色flage = 0;break;}}if( flage && (node == (n - 1) || dfs(node+1, color))) return true;// 疑问2:上面这句也有点问题, 我把他改为://if( flage && node == (n - 1)) return true;// 然后这个for循环后 dfs(node+1, color); 不知道为什么不行}return false;}int main(){int i, j;while( cin >> n && n){char s[30];int flage = 0;//判断是否超过一个节点相连, 如果相连那么1种肯定不行memset(graph, 0, sizeof(graph));for(i = 0; i < n; i++){scanf("%s", s);//接收int len = strlen(s);if(len > 2){flage = 1;//如果有一个s的长度大于2, 那么可能1个频道不行}for(j = 2; j < len; j++){graph[i][s[j] - 'A' ] = 1;//构成graph数组graph[s[j] - 'A'][i] = 1;// 疑问1: 我觉得这句话是多余的, 因为以后来时可以接收到//但是去掉这一句, 就不能Accepted}}if(!flage)//flage还是为0, 那么可以用一个频道cout<< "1 channel needed."<<endl;else if (dfs(0, 2))//从第0个节点给予2中颜色给予检测cout<< "2 channels needed."<<endl;else if (dfs(0, 3))cout<< "3 channels needed."<<endl;else//有四色定理得,最多四种cout<< "4 channels needed."<<endl;}return 0;}


下面在复制一个代码, 这段代码看似更简单

#include <stdio.h>#include <string.h>int graph[26][26];int main(){// freopen("in.txt","r",stdin); int n,i,j,len,max,d[27],channel[26];//channel[]存放各个发射器使用的频道编号 char s[50]; while(scanf("%d",&n)&&n) {  memset(graph,0,sizeof(graph));  memset(channel,0,sizeof(channel));  for(i=0;i<n;i++)   //建立有向图  {   scanf("%s",s);   len=strlen(s);   for(j=2;j<len;j++)    graph[i][s[j]-'A']=1;  }  max=0;  for(i=0;i<n;i++)  {   memset(d,0,sizeof(d));   for(j=0;j<i;j++)  //寻找有冲突的频道编号    if(graph[i][j])     d[channel[j]]=1;//d[k]==1表示k频道有冲突   for(j=1;;j++)   //寻找可以使用的编号最小的频道    if(d[j]==0)     break;   channel[i]=j;   if(j>max)    max=j;     }  if(max==1)   printf("1 channel needed.\n");  else   printf("%d channels needed.\n",max); } return 0;}

第二段代码来自轩辕剑云中界的博客


原创粉丝点击