题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001

题意:

  有n个城市,m条双向道路,每条道路走一次需要花费路费v。你可以将任意一个城市作为起点出发,然后遍历每一个城市,并保证同一个城市最多经过2次。问你遍历这些城市的最小费用是多少。

题解:

  传统的TSP问题中,每个城市只能经过一次,做法为三重for循环,分别枚举城市的state、现在所处位置i、下一步要到达的城市j。

  

  核心Code:

 memset(dp,-,sizeof(dp));
dp[<<start][start]=;
for(int state=;state<(<<n);state++)
{
for(int i=;i<n;i++)
{
if(dp[state][i]!=-)
{
for(int j=;j<n;j++)
{
if(i!=j && !((state>>j)&))
{
if(dp[state|(<<j)][j]==- || dp[state|(<<j)][j]>dp[state][i]+dis[i][j])
{
dp[state|(<<j)][j]=dp[state][i]+dis[i][j];
}
}
}
}
}
}

  在这道题中,与传统TSP的唯一区别是每个城市最多经过的次数由1次变为了2次。那么表示每座城市的状态state也应该相应改为用三进制数表示,每一位上的数字代表对应城市已经经过的次数。

  所以把所有的二进制改为三进制就好啦 ( ̄▽ ̄)~*

  注:不用对于每一个起点分别求一次dp,会T。。。在开始要把所有的dp[update(0, i)][i] = 0

AC Code:

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#define MAX_N 15
#define MAX_S 60000
#define INF 100000000 using namespace std; const int POW[]={,,,,,,,,,,,,,,}; int n,m;
int a,b,v;
int ans;
int dis[MAX_N][MAX_N];
int dp[MAX_S][MAX_N]; void init()
{
for(int i=;i<n;i++)
{
for(int j=;j<n;j++)
{
dis[i][j]=INF;
if(i==j) dis[i][j]=;
}
}
} void read()
{
for(int i=;i<m;i++)
{
cin>>a>>b>>v;
dis[a-][b-]=min(dis[a-][b-],v);
dis[b-][a-]=min(dis[b-][a-],v);
}
} int query(int a,int k)
{
return a/POW[k]%;
} int update(int a,int k)
{
return a+POW[k];
} bool check(int state)
{
for(int i=;i<n;i++)
{
if(query(state,i)==) return false;
}
return true;
} void solve()
{
ans=INF;
memset(dp,-,sizeof(dp));
for(int i=;i<n;i++)
{
dp[update(,i)][i]=;
}
for(int state=;state<POW[n];state++)
{
for(int i=;i<n;i++)
{
if(dp[state][i]!=-)
{
for(int j=;j<n;j++)
{
if(i!=j && query(state,j)<)
{
int nex=update(state,j);
if(dp[nex][j]==- || dp[nex][j]>dp[state][i]+dis[i][j])
{
dp[nex][j]=dp[state][i]+dis[i][j];
}
}
}
if(check(state)) ans=min(ans,dp[state][i]);
}
}
}
} void print()
{
if(ans==INF) cout<<-<<endl;
else cout<<ans<<endl;
} int main()
{
while(cin>>n>>m)
{
init();
read();
solve();
print();
}
}

HDU 3001 Travelling:TSP(旅行商)【节点最多经过2次】的更多相关文章

  1. hdu 3001 Travelling (TSP问题 )

    Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. HDU - 3001 Travelling(三进制状压dp)

    Travelling After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best ch ...

  3. hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp

    题目链接 题意 给定一个\(N\)个点的无向图,求从任意一个点出发,经过所有点的最短路径长度(每个点至多可以经过两次). 思路 状态表示.转移及大体思路 与 poj 3311 Hie with the ...

  4. hdu 3001 Travelling(状态压缩 三进制)

    Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. hdu 3001 Travelling (三进制)【状压dp】

    <题目链接> 题目大意: 给出n个点和m条边,求经过所有点所需的最小花费,每个点最多经过两次. 解题分析: TSP问题类型,由于此题每个点有三种状态,所以采用三进制状态压缩,0.1.2 分 ...

  6. HDU 3001 Travelling(状态压缩DP+三进制)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目大意:有n个城市,m条路,每条路都有一定的花费,可以从任意城市出发,每个城市不能经过两次以上 ...

  7. HDU 3001 Travelling 3进制状压dp

    题意:10个点,若干条边,边有花费,每个点最多走两次,求走过所有点,花费最少 分析:因为每个点最多走两次,所以联想到3进制,然后枚举状态,就行了(我也是照着网上大神的代码写的) #include &l ...

  8. Hdu 3001 Travelling 状态DP

    题目大意 一次旅游,经过所有城市至少一次,并且任何一座城市访问的次数不能超过两次,求最小费用 每个城市最多访问两次,用状态0,1,2标识访问次数 把城市1~N的状态按照次序连接在一起,就组成了一个三进 ...

  9. HDU 3001 Travelling (三进制状态压缩 DP)

    题意:有 n 个city,能够选择任一城市作为起点,每一个城市不能訪问超过2次, 城市之间有权值,问訪问所有n个城市须要的最小权值. 思路:由于每一个城市能够訪问最多两次,所以用三进制表示訪问的状态. ...

随机推荐

  1. 手机端 图片的移动缩放旋转兼容touch

    //缩放var initialScale = 1;var currentScale = 1;touch.on('#target', 'pinch', function (ev) { currentSc ...

  2. Python序列类型

    Python序列类型 序列:字符.列表.元组 所有序列都支持迭代 序列表示索引为非负整数的有序对象集合 字符和元组属于不可变序列,列表可变 1)字符 字符串字面量:把文本放入单引号.双引号或三引号中: ...

  3. View学习(三)- View的布局(layout)过程

    前段开始学习View的工作原理,前两篇博客的草稿都已经写好了,本想一鼓作气写完所有的相关文章,然后经历了一段连续加班,结果今天准备继续写文章时,把之前写好的东西都忘记了,又重新梳理了一遍,所以说那怕就 ...

  4. es6知识总结--3

    es6知识总结--3 es6对咱们es3,es5的数据类型进行了升级下边说新APIs! js数据类型有Number.String .oject.Boolean.Null.Undefined六种数据类型 ...

  5. CJOJ 1131 机器分配 / Luogu 2066 机器分配 (动态规划)

    CJOJ 1131 机器分配 / Luogu 2066 机器分配 (动态规划) Description Luogu: 总公司拥有高效设备M台,准备分给下属的N个分公司.各分公司若获得这些设备,可以为国 ...

  6. Azure PaaS服务密钥的安全性

    Azure PaaS服务,比如存储,Redis缓存,服务总线,IoT中心等等,一般通过密钥来认证客户端,也就是说只有提供正确密钥的客户端才能访问和使用对应的Azure PaaS服务,所以这个密钥是很重 ...

  7. CSS边框(圆角、阴影、背景图片)

    1.圆角  border-radius是向元素添加圆角边框. 使用方法: border-radius:10px; /* 所有角都使用半径为10px的圆角 */ border-radius: 5px 4 ...

  8. android - 解决“应用自定义权限重名”

    背景 现场的开发今天跟我说,测试包装不上!报错"应用自定义权限重名"!!! 网上百度下关键字,发现魅族手机有这个毛病,顺藤摸瓜:"http://bbs.flyme.cn/ ...

  9. Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

    Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...

  10. 【ES6】变量的解构赋值

    1. 数组 var [a, b, c] = [1, 2, 3]; let [a, [b], d] = [1, [2, 3], 4]; 默认值生效的条件是,对象的属性值严格等于undefined. [x ...