HDU 3001 Travelling
2016-04-19 19:01
369 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001
题意:有n个城市,有一个人想全部逛一遍,但是每个城市最多经过两次,他可以从任意一个城市出发,问最小消费。
思路:三进制TSP的状态压缩DP。先预处理出来状态S对应的每一位的值。然后枚举状态以及当前在的城市编号和上一个所在的城市。
题意:有n个城市,有一个人想全部逛一遍,但是每个城市最多经过两次,他可以从任意一个城市出发,问最小消费。
思路:三进制TSP的状态压缩DP。先预处理出来状态S对应的每一位的值。然后枚举状态以及当前在的城市编号和上一个所在的城市。
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdlib> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <sstream> #include <queue> #include <utility> using namespace std; #define rep(i,j,k) for (int i=j;i<=k;i++) #define Rrep(i,j,k) for (int i=j;i>=k;i--) #define Clean(x,y) memset(x,y,sizeof(x)) #define LL long long #define ULL unsigned long long #define inf 0x7fffffff #define mod %100000007 #define mp make_pair #define fi first #define se second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m=(l+r)>>1 int n,m; int a[12][12]; int state[60000][11]; //存每一个状态的三进制下每一位的值。 int Tree_Pow[12]; int dp[60000][11]; void init() { Tree_Pow[0] = 1; rep(i,1,10) Tree_Pow[i] = 3 * Tree_Pow[i-1]; rep(i,1,Tree_Pow[10]) { int temp = i; Rrep(j,10,1) { while( temp >= Tree_Pow[j-1] ) { temp -= Tree_Pow[j-1]; state[i][j]++; } } } } int main() { init(); while( ~scanf("%d%d",&n,&m) ) { Clean(a,0); int ta,tb,tc; int ans = inf; rep(i,1,m) { scanf("%d%d%d",&ta,&tb,&tc); if ( !a[ta][tb] ) { a[ta][tb] = tc; a[tb][ta] = tc; } else { a[ta][tb] = min(a[ta][tb] , tc); a[tb][ta] = min(a[tb][ta] , tc); } } int uplim = Tree_Pow ; Clean(dp,-1); rep(i,1,uplim-1) { rep(j,1,n) if ( state[i][j] ) { int last = i - Tree_Pow[j - 1];//得到上一个状态 if ( last == 0 ) { if ( state[i][j] == 1 ) { dp[i][j] = 0; } } else { rep(k,1,n) //枚举上一个城市 if ( k != j && state[last][k] && dp[last][k] != -1 && a[k][j] ) { if ( dp[i][j] == -1 ) dp[i][j] = dp[last][k] + a[k][j]; else dp[i][j] = min( dp[i][j] , dp[last][k] + a[k][j] ); } } } bool can = true; rep(j,1,n) if ( state[i][j] == 0 ) can = false; if ( can ) // 检查当前状态是否将所有的城市都遍历过了 rep(j,1,n) if (dp[i][j]!=-1) ans = min( ans , dp[i][j] ); } if ( ans == inf ) puts("-1"); else cout<<ans<<endl; } return 0; }
相关文章推荐
- 关于postman使用的几点注意事项
- 8种传值方式
- Linux学习笔记--free命令(查看内存信息的命令)
- iOS 处理图片的一些小 Tip
- 第七周 项目三
- C语言单元测试框架Check
- C中一些运算符的使用
- 为什么Hibernate的OneToMany用Set集合而不用list
- SEGGER_RTT的使用
- mysql-proxy安装报错
- Android——listview android:cacheColorHint,android:listSelector属性作用
- 最大熵模型介绍及实现
- 从字符串中提取数字
- sqlserver中创建链接服务器图解教程
- 12rescue
- poj 2398 Toy Storage
- HDU Labyrinth DP
- 关于如何优化eclipse启动时间
- 进程和线程(Processes and Threads)——翻译自developer.android.com
- redis自动安装脚本(只安装redis)