UVA 140 Bandwidth 带宽(DFS+最优性剪枝)
Posted linme
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA 140 Bandwidth 带宽(DFS+最优性剪枝)相关的知识,希望对你有一定的参考价值。
#include<iostream>
#include<cstdio>
#include<set>
#include<cstring>
using namespace std;
set<int>p[27];
int b[9],vis[9],ans[9],s[9],n=0,small=10,cha; //n<=8,所以最大带宽肯定不会超过10
void dfs(int cur,int now)//当前第几个,当前最大值
{
if(cur==n&&small!=now){//注意字典序,较后来相同带宽的最优解不能取
for(int i=0;i<n;i++)
ans[i]=s[i];
small=now;
cha=1; //标记已经得到一个解,small已经更新,作为剪枝2的条件
return ;
}
for(int i=0;i<n;i++){
if(!vis[i]){
s[cur]=b[i];
int ok=1;
if(!p[s[cur]].empty()){
int cnt=0; //记录前面未出现的相邻节点个数
set<int>::iterator it=p[s[cur]].begin();
for(;it!=p[s[cur]].end();it++){//枚举查找对比是否有相邻节点
int has=1;
for(int k=0;k<cur;k++)
if(s[k]==*it){//只要将当前与前面所有相邻节点都计算一遍就行(其它已经计算过了)
if(cur-k >= small){ok=0;break;}//剪枝1
if(cur-k>now)now=cur-k;
has=0; //如果有 cnt就不用增加
break;
}
if(has&&cha){ //剪枝2
if(++cnt>=small){ok=0;break;}//
}
if(!ok)break;
}
}
if(!ok)continue;//下一个
vis[i]=1;
dfs(cur+1,now);
vis[i]=0; //恢复标记
}
}
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
char temp,t;
while(1){//循环输入
t=temp=0;
n=0,small=20,cha=0;
memset(b,0,sizeof(b));memset(vis,0,sizeof(b));memset(ans,0,sizeof(b));memset(s,0,sizeof(b));
for(int i=0;i<26;i++)p[i].clear();
while(scanf("%c",&temp)){
if(temp=='#')break;
getchar();//去掉 :
while(scanf("%c",&t)&&t!=';'&&t!='
'){//相互保存在set里
p[temp-'A'].insert(t-'A');
p[t-'A'].insert(temp-'A');
}
if(t=='
')break;
}
if(temp=='#')break;
for(int i=0;i<26;i++)if(!p[i].empty())b[n++]=i;
dfs(0,0);//当前层数及当前带宽最大值为0
for(int i=0;i<n;i++){
printf("%c ",ans[i]+'A');
}
cout<<"-> "<<small<<endl;
}
return 0;
}
以上是关于UVA 140 Bandwidth 带宽(DFS+最优性剪枝)的主要内容,如果未能解决你的问题,请参考以下文章
UVa140 Bandwidth 小剪枝+双射小技巧+枚举全排列+字符串的小处理