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!='\n'){//相互保存在set里
            p[temp-'A'].insert(t-'A');
            p[t-'A'].insert(temp-'A');
        }
        if(t=='\n')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;
}

猜你喜欢

转载自www.cnblogs.com/linme/p/12220726.html