UVA-140 Bandwidth (回溯+剪枝)

题目大意:求一个使带宽最小的排列和最小带宽。带宽是指一个字母到其相邻字母的距离最大值。

题目分析:在递归生成全排列的过程中剪枝,剪枝方案还是两个。一、当前解不如最优解优时,减去;二、预测的理想解不必最优解优时,减去。将与当前最后一个位置上的字母相邻的字母全部接过来,便得理想解。

代码如下:

# include<iostream>
# include<cstdio>
# include<string>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;
char p[100];
vector<int>v[30],w;
int ans,vis[30],n;
string ansp;
void init()
{
    int l=strlen(p);
    int now;
    for(int i=1;i<l;++i){
        if(p[i]==‘;‘)
            continue;
        if(p[i]==‘:‘){
            now=p[i-1]-‘A‘;
            continue;
        }
        if(p[i-1]!=‘;‘){
            vector<int>::iterator it;
            it=find(v[now].begin(),v[now].end(),p[i]-‘A‘);
            if(it==v[now].end())
                v[now].push_back(p[i]-‘A‘);
            it=find(v[p[i]-‘A‘].begin(),v[p[i]-‘A‘].end(),now);
            if(it==v[p[i]-‘A‘].end())
                v[p[i]-‘A‘].push_back(now);
        }
    }
    for(int i=0;i<30;++i)
        sort(v[i].begin(),v[i].end());
    w.clear();
    vector<int>::iterator it;
    for(int i=0;i<l;++i){
        if(p[i]==‘:‘||p[i]==‘;‘)
            continue;
        it=find(w.begin(),w.end(),p[i]-‘A‘);
        if(it==w.end())
            w.push_back(p[i]-‘A‘);
    }
    sort(w.begin(),w.end());
    n=w.size();
}
int f(string app,int g,int pos)
{
    for(int i=0;i<app.size();++i){
        if(i==pos)
            continue;
        if(app[i]==g+‘A‘)
            return i;
    }
    return pos;
}
int get(string app)
{
    int res=0;
    int l=app.size();
    for(int i=0;i<l;++i){
        for(int j=0;j<v[app[i]-‘A‘].size();++j){
            int pos=f(app,v[app[i]-‘A‘][j],i);
            res=max(res,abs(pos-i));
        }
    }
    return res;
}
void dfs(int cur,int now,string ap)
{
    if(cur==n){
        if(now<ans){
            ans=now;
            ansp=ap;
        }
        return ;
    }
    if(now>=ans)
        return ;
    int l=ap.size();
    if(l>0){
        string app=ap;
        for(int i=0;i<v[ap[l-1]-‘A‘].size();++i){
            int j;
            for(j=0;j<l;++j)
                if(v[ap[l-1]-‘A‘][i]==ap[j]-‘A‘)
                    break;
            if(j>=l)
                app+=char(v[ap[l-1]-‘A‘][i]+‘A‘);
        }
        if(get(app)>=ans)
            return ;
    }
    for(int i=0;i<n;++i){
        if(vis[w[i]])
            continue;
        vis[w[i]]=1;
        dfs(cur+1,get(ap+char(w[i]+‘A‘)),ap+char(w[i]+‘A‘));
        vis[w[i]]=0;
    }
}
int main()
{
    while(scanf("%s",p))
    {
        if(p[0]==‘#‘)
            break;
        for(int i=0;i<30;++i)
            v[i].clear();
        init();
        ans=100;
        ansp.clear();
        memset(vis,0,sizeof(vis));
        dfs(0,0,"");
        int len=ansp.size();
        for(int i=0;i<len;++i)
            printf("%c ",ansp[i]);
        printf("-> %d\n",ans);
    }
    return 0;
}

  

时间: 2024-08-24 17:15:45

UVA-140 Bandwidth (回溯+剪枝)的相关文章

[2016-02-20][UVA][140][Bandwidth]

UVA - 140 Bandwidth Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an ordering on the elements in V, then the bandwidth 

uva 140 Bandwidth (全排列+暴力枚举)

uva 140 Bandwidth Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an ordering on the elements in V, then the bandwidth of a node v is defined as the maximum distance in the ordering between v and any node to which it

UVa 140 Bandwidth(DFS 回溯 剪枝)

题意  有一个无向图  对于其所有顶点的一个排列 称一顶点与所有与其有边的其它顶点在排列中下标差的最大值为这个顶点的带宽   而所有顶点带宽的最大值为这个排列的带宽   求这个图带宽最小的排列 枚举排列  ans记录当前找到的最小带宽  枚举过程中一旦出现带宽大于ans的也就不用再扩展了  这样枚举完就得到了答案 #include<cstdio> #include<cstring> using namespace std; const int N = 50; int n, ans,

uva 140 bandwidth (好题) ——yhx

 Bandwidth  Given a graph (V,E) where V is a set of nodes and E is a set of arcs in VxV, and an ordering on the elements in V, then the bandwidth of a node v is defined as the maximum distance in the ordering between v and any node to which it is con

UVA - 140 Bandwidth(带宽)(全排列)

题意:给定图,求是带宽最小的结点排列. 分析:结点数最多为8,全排列即可.顶点范围是A~Z. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #i

uva 140 Bandwidth(全排列+递归)

快睡觉的时候1A的把序列全排列,递归暴力判断就ok啦,我改成对应的整数存了,a数组存的是所有的字符的排列, b数组存的是所有开始节点的排列,map[i][j]数组存的是i为起点,与j相邻 贴代码: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<limits.h> #include<math.h> #include<algorithm> using na

UVA10317- Equating Equations(回溯+剪枝)

题目链接 题意:给出一个式子,但这个式子不一定是等式,在'+','-'符号位置不变的情况下,重新排列数字的位置,使其成为等式,如果可以的话,输出其中一种排列方式. 思路:我们将等号右边的数全部移动到等号右边,例如a+b-c=d-e,移动后变成a+b+e-(c+d)=0,也就是a+b+e=c+d,所以当式子可以变化成等式时,所有数的和必然是偶数.那么问题可以转化为在n个数中找出m个数(m的值为等号左边的整数的数量),使m个 数的和为从和的一半. #include <iostream> #incl

HDU1016 Prime Ring Problem (回溯 + 剪枝)

题意: 给你一个数字N(N <= 20),要求你把这N个数组成一个环,环内的数字不能重复,左右相邻的两个的和是素数.给出最后的答案. 思路: 利用回溯剪枝算法,N个数,每个数有N种状态,枚举这N个状态,枚举过程中剪枝优化. 代码: #include <cstdio> #include <iostream> #include <cstring> #include <cstring> #include <cmath> #include <

HDU1010 Tempter of the Bone(回溯 + 剪枝)

题意: 输入一个 N * M的迷宫,这个迷宫里'S'代表小狗的位置,'X'代表陷阱,‘D’代表门,‘.’代表可行走的地方,小狗每次可以选择往周围的四个方向行走,问这个小狗能否正好T步找到门. 思路: 利用回溯 + 剪枝,这道题剪枝特别重要. 剪枝一: 可以把图看成这样: 1 0 1 0 10 1 0 1 01 0 1 0 10 1 0 1 01 0 1 0 1 则假设从点 a(i + j,横纵坐标之和) 走到点 b(i + j) ,如果 a 和 b 的奇偶性相同,那么从 a 到 b 必须是偶数步

uva10400 - Game Show Math(回溯+剪枝)

题目:uva10400 - Game Show Math(回溯+剪枝) 题目大意:给出N个数,并且给出一个目标数值,要求用上面的数字(全部),并且顺序不能乱,然后用+-*/这些操作,问最终能不能得到目标数值.这里要注意给出的数会在[-32000,32000]之间, 并且要用除法的时候,只有在能整除的时候才能用.并且中间计算结果不能超过[-32000,32000]范围.如果超过这个操作不能做. 解题思路:回溯加剪枝,将每一层计算的结果都保存下来,如果在同一层发现值出现过,并且之前计算发现这样往后是