题目:http://poj.org/problem?id=1129
跟竞赛宝典上那个题一样,给出一个区域,后面是相连的区域,求最小染色数。
由四色定理可知,最大是4种,可作为一种枝剪方法。
dfs:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int mp[30][30],v[30],n,flag;
void dfs(int x){
if(x==n+1){
flag=1;
int max1=1;
for(int i=1;i<=n;i++)
max1=max(v[i],max1);
if(max1==1)
printf("1 channel needed.\n");
else
printf("%d channels needed.\n",max1);
return ;
}
for(int i=1;i<=4;i++){
int j;
for(j=1;j<=n;j++){
if(mp[x][j]&&v[j]==i)
break;
}
if(j==n+1){
v[x]=i;
dfs(x+1);
if(flag)
return; //一种情况即可
}
}
}
int main(){
int x,y,l;
char str[100];
while(scanf("%d",&n)&&n){
flag=0;
memset(mp,0,sizeof(mp));
memset(v,0,sizeof(v));
for(int i=0;i<n;i++){
scanf("%s",str);
l=strlen(str);
x=str[0]-'A'+1;
for(int j=2;j<l;j++){
y=str[j]-'A'+1;
mp[x][y]=1;
}
}
dfs(1);
}
return 0;
}
非递归:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int mp[30][30],v[30],n,flag;
bool judge(int k){
for(int i=1;i<=n;i++){
if(mp[k][i]){
if(v[i]==v[k]&&k!=i)
return 0;
}
}
return 1;
}
void solve(){
int k=1;
while(1){
v[k]+=1;
while(v[k]<=4&&!judge(k)) //k不行,直到找到可以的k
v[k]+=1;
if(v[k]>4){
v[k]=0;
k--; //如果超过4还不行,回到上一区域
continue;
}
if(k==n+1)
break;
else
k++; //没染完就下一区域
}
int max1=1;
for(int i=1;i<=n;i++)
max1=max(v[i],max1);
if(max1==1)
printf("1 channel needed.\n");
else
printf("%d channels needed.\n",max1);
return ;
}
int main(){
int x,y,l;
char str[100];
while(scanf("%d",&n)&&n){
flag=0;
memset(mp,0,sizeof(mp));
memset(v,0,sizeof(v));
for(int i=0;i<n;i++){
scanf("%s",str);
l=strlen(str);
x=str[0]-'A'+1;
for(int j=2;j<l;j++){
y=str[j]-'A'+1;
mp[x][y]=1;
}
}
solve();
}
return 0;
}