uva140_dfs(回溯)最优性剪枝


///
作者:tt2767
声明:本文遵循以下协议自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0
查看本文更新与讨论请点击:http://blog.csdn.net/tt2767
链接被删请百度: CSDN tt2767
///


题解:
1.原书中已经说明,如果两个节点的带宽 >= 最小带宽,无论如何也不可能比原解更优,应该剪掉。

2.注意此题读入的时候一定要按 字典序 存储,这样计算出的最小值才是符合要求的

3.注意strtok的用法


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
//
#include<iostream>
#include<algorithm>
#include<string>
#include <iterator>
#include<sstream>
#include<functional>
#include<numeric>
///
#include<vector>
#include<map>
#include <stack>
#include<queue>
#include<set>
#include <bitset>
#include <list>
using namespace std;
#define lch(x)  ((x) << 1)
#define rch(x) ((x)<<1|1)
#define dad(x) ((x)>>1)
#define lowbit(x) ((x)&(-x))
typedef  long long int LL;
const int INF = ~0U>>1;
const double eps = 1e-6;
const long double PI = acos(0.0) * 2.0;
const int N = 10+200;
map<char,int> id;

int mi ,n;
char in[N];
int v[N],ans[N],tmp[N];
bool vis[N],G[N][N];

bool read();
void dfs(int cur , int x);
int ID(char x){return id[x];}

int main()
{
    //ios::sync_with_stdio(false);
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
#endif
    while(read())
    {
        mi = n; //带宽最大为n
        dfs(0,0);   //dfs(当前位置,上一次算的带宽)
        for(int  i = 0 ; i < n ; i++)       printf("%c ",v[ ans[i] ]+'A');
        printf("-> %d\n",mi);
    }
    return 0;
}


bool read()
{
    gets(in);
    if(in[0]=='#')  return 0;
    char * p,*s=in;
    memset(vis,0,sizeof(vis));
    int l = strlen(in);
    for(int i = 0 ; i< l ; i++) if(isalpha(in[i])) vis[in[i]-'A']=1;  //字典序查找点
    n = 0;          //按字典序把点映射,并收集起来
    for(int i = 0 ; i < 27 ; i++)    if(vis[i])    v[ id[i+'A']=n++ ] = i;

    memset(G,0,sizeof(G));
    while(p = strtok(s,";"))//分割字符串
    {
        for(int i = 2 ; p[i]!='\0' ; i++)   //转化成邻接矩阵储存,方便查询
            G[ ID(p[0])][ ID(p[i]) ] = G[ ID(p[i])][ ID(p[0])] = 1;
        s = NULL;
    }

    memset(vis,0,sizeof(vis));
    return 1;
}

void dfs(int cur , int x)
{
    if(cur == n)//能运行到这一步的值必定比前一个小
    {                  //更新它
        mi = x;
        memcpy(ans,tmp,sizeof(tmp));
        return ;
    }

    for(int  i = 0 ; i < n ; i++)//回溯生成排列
    {       
        if(!vis[i])
        {
            vis[i] = 1;
            tmp[cur] = i;
            int dk = 0;
            for(int j = 0 ; j < cur ; j++)
            {
                if(G[ i ][ tmp[j] ])
                {
                    dk = cur - j;
                    break;
                }
            }
            dk = max(x,dk);
            if(dk < mi)    dfs(cur+1,dk);   //如果某个节点的带宽比当前最小带宽大,剪掉它
            vis[i] = 0;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值