题目链接: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. 【WPF】在新线程上打开窗口

    当WPF应用程序运行时,默认会创建一个UI主线程(因为至少需要一个),并在该UI线程上启动消息循环.直到消息循环结束,应用程序就随即退出.那么,问题就来了,能不能创建新线程,然后在新线程上打开一个新窗 ...

  2. 原生js表单序列化----- FormData

    <style type="text/css"> .progress{ height: 10px; width: 600px; border: 1px solid red ...

  3. usaco 2002 月赛 Chores 题解

    Description Farmer John's family pitches in with the chores during milking, doing all the chores as ...

  4. js-txt文本处理

    js-txt文本处理 写自己主页项目时所产生的小问题拿出来给大家分享分享,以此共勉. ---DanlV TextArea的换行符处理 TextArea文本转换为Html:写入数据库时使用 js获取了t ...

  5. 互联网级监控系统必备-时序数据库之Influxdb集群及踩过的坑

    上篇博文中,我们介绍了做互联网级监控系统的必备-Influxdb的关键特性.数据读写.应用场景: 互联网级监控系统必备-时序数据库之Influxdb 本文中,我们介绍Influxdb数据库集群的搭建, ...

  6. Javasript 正则匹配任意字符

    今天在写Js匹配任意字符的时候发现使用.不好使,当输入内容有回车的时候就会失效. 后来上网查,发现js的任意字符不包括\n. 本来想写一个trim后长度为10的正则验证,最后使用[\s|\S]来代替任 ...

  7. Linux 学习记录 四(Bash 和 Shell scirpt)

    一.什么是 Shell? 狭义的shell指的是指令列方面的软件,包括基本的Linux操作窗口Bash等,广义的shell则包括 图形接口的软件,因为图形接口其实也可以操作各种驱动程序来呼叫核心进行工 ...

  8. 20170721_python字符串操作_《python语言及其应用》

    str = 'abcde...wxyz' [num]提取指定字符 str[0] == 'a' str[1] == 'b' str[-1] == 'z' [start:end:step]分片/切片,一定 ...

  9. Spring Ioc-依赖注入的几种方式

    一 setter方法注入 配置文件如下: <bean id="helloAction" class="org.yoo.action.SpringSetterHell ...

  10. Java设计模式学习笔记,一:单例模式

    开始学习Java的设计模式,因为做了很多年C语言,所以语言基础的学习很快,但是面向过程向面向对象的编程思想的转变还是需要耗费很多的代码量的.所有希望通过设计模式的学习,能更深入的学习. 把学习过程中的 ...