题目链接: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. 第一个SpringMVC实例和解析(HelloSpringMVC)

    1. 开发步骤: (1)增加Spring支持 下载Spring安装包和其依赖的commons-logging.jar,复制到项目Web应用的lib文件夹(WebRoot/WEB-INF/lib): S ...

  2. Spring Boot1.5.4 AOP实例

    原文:https://github.com/x113773/testall/issues/12 1. 还是首先添加依赖(使用当前springboot的默认版本)```<dependency> ...

  3. 数据库--释放mysql数据库资源

    背景 nikeodong之前做了项目的数据库主从,在全备的过程发现数据库是越来越大了:最后发现是资源不释放的问题. 目的 为了解决mysql资源不释放的问题. 步骤 1.vim /etc/my.cnf ...

  4. 软考 程序员 下午考题 c语言 笔记

    1. 数组名 是表示数组空间首地址的指针常量,程序中不允许对常量赋值. 如 int  a[];   a就是数组名,表示数组控件首地址的指针常量 a = 0;是错误的,不允许对指针常量赋值 &a ...

  5. 使用 VS2017 和 js 进行桌面程序开发 - electron 之 Hello Word

    现在基于 js 和 web浏览器核心构建的 C/S 程序越来越多,比如微信桌面版(基于 duilib 和 cef).VS CODE(基于electron)等,出于了解的目的,最近学习了 electro ...

  6. MySQL oracle 分页

    (1)MySql的Limit m,n语句 Limit后的两个参数中,参数m是起始下标,它从0开始:参数n是返回的记录数.我们需要分页的话指定这两个值即可. 比如:查询10行记录,起始行从3开始 SEL ...

  7. 钉钉 机器人接入 自定义webhook

    钉钉出了个webhook机器人接入,自定义的机器人支持随时post消息到群里: 昨天就尝试着用C#写了个: 一开始用python写,但是莫名的提示  {"errmsg":" ...

  8. python-web.py 入门介绍

    内容来源:webpy.org 介绍: 1.python中web.py 是一个轻量级Python web框架,它简单而且功能强大.web.py是一个开源项目. 2.安装很简单:pip install w ...

  9. Phpcms 前台页面实现分页

    phpcms开发就是模仿里面原有的方法进行扩展,前台要实现分页,就去找后台页面的分页实现. 如后台 扩展->后台操作日志,就有分页展示. 1.先去添加自己的分页方法(千万不要在原来的方法上修改, ...

  10. 20170709_python_学习记录

    a='ABC';变量赋值时发生了什么 1.在内存中创建一个字符串'ABC' 2.在内存中创建一个变量a指向字符串'ABC' list [] 相当于数组 指向可以变动 str[1,2,3,4] str. ...