HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
题意:
每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短。
思路:
给了很多重边,选最小的留下即可。任意点可能无法直接到达,所以先执行一次floyd,算出任意点对之间可达的最短距离。
(1)先考虑穷举的方法,将2~n个这n-1个数字的所有组合情况都算一遍,复杂度是 15!=1 3076 7436 8000,那是真的TSP了,不可能实现。
(2)上面的方法中有没有多余的计算量?有的!里面还是有贪心可以运用的地方。对于当前遍历过了哪些点,我们只需要知道最后一个点是什么,中间的点的顺序是所所谓的,那么最后一个遍历的可以是2~n,而中间那些可以是其他的2~n中的数。起点1的距离更新为0,接下来递推就行了。递推方法是,穷举所有的中间状态s,然后以这些状态去穷举下一个到达的点(此点不在s中)。
状态方程是: dp[s|(1<<(i-1))][i]=min(dp[s][j]+g[j][i] ); s表示已经遍历过的点,j是最后那个点,i是未遍历过的点,从j走到i。
290ms算可以了。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=;
int g[N][N], dp[<<N][N]; void floyd(int n)
{
for(int k=; k<=n; k++)
for(int i=; i<=n; i++)
for(int j=; j<=n; j++)
g[i][j]=min( g[i][j], g[i][k]+g[k][j]); } int cal( int n )
{
floyd(n);
memset(dp, 0x7f, sizeof(dp));
dp[][]=;
for(int s=; s<(<<n); s+=) //穷举状态
{
for(int i=; i<=n; i++) //设最后访问的点是i。i!=0
{
if( ( <<(i-) ) & s ) continue; //s中的第i位必须为0,即未访问过。
for(int j=; j<=n; j++)
{
if( s&(<<(j-)) ) //穷举s中出现过的1的位置。
dp[s|(<<(i-))][i]=min( dp[s|(<<(i-))][i], dp[s][j]+g[j][i] );
}
}
}
int ans=INF;
for(int i=; i<=n; i++) //最后访问的点不会是起点1。
ans=min(ans, dp[(<<n)-][i]+g[i][]);
return ans==INF? : ans; //只有1个点的情况
}
int main()
{
//freopen("input.txt", "r", stdin);
int t, n, m, a, b, c;
cin>>t;
while(t--)
{
scanf("%d%d", &n, &m);
memset(g, 0x3f, sizeof(g));
for(int i=; i<=n; i++) g[i][i]=; //初始化
for(int i=; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
g[b][a]=g[a][b]=min(g[a][b], c);
}
printf("%d\n", cal(n));
}
return ;
}
AC代码
HDU 5418 Victor and World (可重复走的TSP问题,状压dp)的更多相关文章
- POJ 1185 - 炮兵阵地 & HDU 4539 - 郑厂长系列故事——排兵布阵 - [状压DP]
印象中这道题好像我曾经肝过,但是没肝出来,现在肝出来了也挺开心的 题目链接:http://poj.org/problem?id=1185 Time Limit: 2000MS Memory Limit ...
- HDU - 6344 2018百度之星资格赛 1001调查问卷(状压dp)
调查问卷 Accepts: 1289 Submissions: 5642 Time Limit: 6500/6000 MS (Java/Others) Memory Limit: 262144 ...
- HDU 4539郑厂长系列故事――排兵布阵(状压DP)
HDU 4539 郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 //#pragma co ...
- hdu 2809(状压dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2809 思路:简单的状压dp,看代码会更明白. #include<iostream> #in ...
- hdu 2167(状压dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2167 思路:经典的状压dp题,前后,上下,对角8个位置不能取,状态压缩枚举即可所有情况,递推关系是为d ...
- ACM: HDU 5418 Victor and World - Floyd算法+dp状态压缩
HDU 5418 Victor and World Time Limit:2000MS Memory Limit:131072KB 64bit IO Format:%I64d & ...
- HDOJ 5418 Victor and World 状压DP
水状压DP Victor and World Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/131072 K (Java ...
- HDU 4284Travel(状压DP)
HDU 4284 Travel 有N个城市,M条边和H个这个人(PP)必须要去的城市,在每个城市里他都必须要“打工”,打工需要花费Di,可以挣到Ci,每条边有一个花费,现在求PP可不可以从起点1 ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
随机推荐
- Mice and Holes
题意: 有 $n$ 只老鼠和 $m$ 个鼠洞,第 $i$ 只老鼠的坐标为 $x_i$,第 $j$ 个鼠洞的坐标为 $p_j$ ,容量为 $c_j$. 第 $i$ 只老鼠钻进第 $j$ 个鼠洞的距离为 ...
- 使用SQL访问MongoDB
使用SQL访问MongoDB 简介 使用SQL访问MongoDB有多种解决方案,就我所知的,除了今天要介绍的MongoDB Connector for BI外,还有Studio 3T,但后者只有在企业 ...
- 线程通讯-Condition
Account类 package com.thread.communication.condition; import java.util.concurrent.TimeUnit; import ja ...
- Linux文件IO操作函数概述
文件概述 Linux中,一切皆文件.文件为操作系统服务和设备提供了一个简单而一致的接口.这意味着程序完全可以像使用文件那样使用磁盘文件.串行口.打印机和其他设备. 也就是说,大多数情况下,你只需要使用 ...
- 洛谷 - P3786 - 萃香抱西瓜 - 状压dp
重构一下就过了,不知道之前错在哪里. #include<bits/stdc++.h> using namespace std; typedef unsigned long long ull ...
- POJ3414(BFS+[手写队列])
贴一发自己写的手写队列-.. #include <stdio.h> #include <iostream> #include <string.h> #include ...
- vm安装mac
需要 vm虚拟机:vm10 mac系统: mac10.9 vm安装mac补丁 : unlokc-all-v120 vm tools for mac10.9: darwin6.0.3.iso ...
- Spring Boot Autowirted注入找不到Bean对象解决方法
报错:Consider defining a bean of type 'xxxxxxxxxxxxx' in your configuration 1. 你应该在 ApplyApplication 启 ...
- 单片机的C语言中位操作用法2
单片机的C语言中位操作用法 在对单处机进行编程的过程中,对位的操作是经常遇到的.C51对位的操控能力是非常强大 的.从这一点上,就可以看出C不光具有高级语言的灵活性,又有低级语言贴近硬件的特点. 这也 ...
- luoguP3796[模板]AC自动机(加强版)
传送门 ac自动机模板,可能我写的ac自动机是有点问题的,所以跑的有些慢 暴力跳fail统计 代码: #include<cstdio> #include<iostream> # ...