HDU3001 Traveling (状压dp+三进制+Tsp问题总结)
(1)这道题最多可以走两次,所以有0, 1, 2三种状态,所以我们要用三进制
如果要用三进制,就要自己初始化两个数组, 一个是3的n次方,一个是三进制数的第几位的数字是什么
void init()
{
three[0] = 1;
REP(i, 1, 11)
three[i] = three[i-1] * 3;
REP(i, 0, three[10])
{
int t = i;
REP(j, 0, 10)
{
digit[i][j] = t % 3;
t /= 3;
if(t == 0) break;
}
}
}
同时这里不能用位运算,因为不是二进制。如果涉及到某一位加1,就加上就好了,不能用|
然后统计答案的时候比较麻烦,要枚举每一位是不是0
(2)凡是涉及到进制的,下标都从0开始。输入的时候记得要下标减减
(3)Tsp问题的基本套路是这样的(我用的是填表法)
dp数组全部初始化为最大值
起点初始化为0,即dp[1 << i][i] = 0
第一层循环枚举所有可能的状态S
第二层枚举当前点i,这里要求这个点已经经过
第二层枚举之前的点j,这里同样要求这个点已经经过
dp[state][i] = min(dp[state][i], dp[state^(1 << i)][j] + dist[j][i])
记住要去掉当前这个点
最后答案就是min(dp[(1 << n) - 1][i])
#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 15;
int dist[MAXN][MAXN], dp[60000][MAXN], n, m;
int three[MAXN], digit[60000][MAXN];
void init()
{
three[0] = 1;
REP(i, 1, 11)
three[i] = three[i-1] * 3;
REP(i, 0, three[10])
{
int t = i;
REP(j, 0, 10)
{
digit[i][j] = t % 3;
t /= 3;
if(t == 0) break;
}
}
}
int main()
{
init();
while(~scanf("%d%d", &n, &m))
{
memset(dist, 0x3f, sizeof(dist));
while(m--)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w); u--; v--; //注意要--
dist[u][v] = dist[v][u] = min(dist[u][v], w);
}
int ans = 1e9;
memset(dp, 0x3f, sizeof(dp)); //初始化不能忘
REP(i, 0, n) dp[three[i]][i] = 0;
REP(S, 0, three[n])
{
bool ok = true;
REP(i, 0, n)
{
if(digit[S][i] == 0) { ok = false; continue; } //i要已经经过。
REP(j, 0, n) if(digit[S][j] >= 1) //j已经经过
dp[S][i] = min(dp[S][i], dp[S-three[i]][j] + dist[j][i]);
}
if(ok)
REP(i, 0, n)
ans = min(ans, dp[S][i]);
}
printf("%d\n", ans == 1e9 ? -1 : ans);
}
return 0;
}
HDU3001 Traveling (状压dp+三进制+Tsp问题总结)的更多相关文章
- Travelling(HDU3001+状压dp+三进制+最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目: 题意:n个城市,m条边,每条边都有一个权值,问你经过所有的城市且每条边通过次数不超过两次 ...
- HDU - 3001 Travelling 状压dp + 三进制 [kuangbin带你飞]专题二
终于刷完搜索专题了. 题意:给定n个城市,每个城市参观不能超过两次,两个城市之间有道路通过需要花费X,求通过能所有城市的最小花费. 思路:每个城市有三个状态0,1,2,可用三进制存储所有城市的访问状态 ...
- hdu3001(状压dp,三进制)
Travelling Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU3001 Travelling —— 状压DP(三进制)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3001 Travelling Time Limit: 6000/3000 MS (Java/ ...
- hdu3001(状压dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意:n 个城市已经 m 条路 以及对应路费 c,要求遍历所有城市最少的路费,每个城市不能超过2 ...
- HDU3001 Travelling 状压DP
哭瞎啊,每一个城市能够经过至多两次,但没有要求必须经过两次.想用 两个状压来乱搞搞.结果自觉得会T.结果 WA了,搞了一下午.没想到用三进制啊.智商捉急,參考了 http://blog.csdn.ne ...
- HDU 4026 Unlock the Cell Phone 状压dp(类似TSP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4026 Unlock the Cell Phone Time Limit: 6000/3000 MS ...
- poj 3311 Hie with the Pie (状压dp) (Tsp问题)
这道题就是Tsp问题,稍微加了些改变 注意以下问题 (1)每个点可以经过多次,这里就可以用弗洛伊德初始化最短距离 (2)在循环中集合可以用S表示更清晰一些 (3)第一维为状态,第二维为在哪个点,不要写 ...
- POJ1185 状压dp(二进制//三进制)解法
很显然这是一道状压dp的题目 由于每个最优子结构和前两行有关,一个显而易见的想法是用三维dp[i][j][k]用来记录在第i行下为j状态,i - 1行为k状态时的最大值,然而dp[100][1 < ...
随机推荐
- Python - def 函数
1.def 函数 如果我们用代码实现了一个小功能,但想要在程序代码中重复使用,不能在代码中到处粘贴这些代码,因为这样做违反了软件工程中 DRY原则. Python 提供了 函数功能,可以将我们这部分功 ...
- Django入门--模板变量、过滤器及静态文件
一.模板变量 我们登录页面后,在页面上会显示姓名等信息,姓名就是模板变量,用来显示登陆者的名字,Django对这些数据进行处理后,返回给前端页面,前端页面进行渲染. 1.模板变量语法规则 1)在htm ...
- python第四周:装饰器、迭代器、内置方法、数据序列化
1.装饰器 定义:本质是一个函数,(装饰其他函数)就是为其他函数添加附加功能 原则:不能修改被装饰函数的源代码,不能修改被装饰函数的调用方式 实现装饰器的知识储备: 函数即“变量”.每当定义一个函数时 ...
- 通过腾讯地图api获取用户位置限制在指定位置区域
<!--在微信中获取用户位置--><script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js">& ...
- JavaScript之Ajax技术
- 【转】C# ArcgisEngine开发中,对一个图层进行过滤,只显示符合条件的要素
有时候,我们要对图层上的地物进行有选择性的显示,以此来满足实际的功能要求. 按下面介绍的方法可轻松实现图层属性过滤显示: 1.当图层已经加载时 private void ShowByFilter(Ax ...
- static final常量变量的正确书写规范
AccountConstants.java类 命名:常量类以Constants单词命名结尾 package com.paic.pacz.core.salesmanage.util; import ja ...
- C++表达式求值(利用数据结构栈)
唉,刚刚用C++又又一次写了一个较完好的表达式求值程序,最后精简后程序还不到100行.这不经让我 想到了大一上学期刚学c语言时自己费了好大的劲,写了几百行并且功能还不是非常齐全(当时还不能计算有括号的 ...
- BZOJ 2728 HNOI2012 与非 高斯消元
题目大意:给定k位二进制下的n个数,求[l,r]区间内有多少个数能通过这几个数与非得到 首先观察真值表 我们有A nand A = not A 然后就有not ( A nand B ) = A and ...
- 0x17 二叉堆
优先队列太好用了手写啥呀 poj1456 经过贪心专题的洗礼以后这题根本就不叫题啊...按时间大到小排每次取最大就好 #include<cstdio> #include<iostre ...