POJ 3311 Hie with the Pie (状压DP)
2015-07-07 19:04
429 查看
题意:n+1个点 从0出发,遍历所有的点最后回到0,每个点可访问多次,求最小花费。
思路:因为每个点可访问多次,所以用一下floyd预处理一下图就好了,然后就是个TSP。
设dp[S][v] 为遍历状态S中的每一个节点,且最后到达S中的v的最小花费。
状态转移方程:dp[S][v] = min(dp[S][v],dp[S - {v}][u] + maps[u][v]).
我的代码:
思路:因为每个点可访问多次,所以用一下floyd预处理一下图就好了,然后就是个TSP。
设dp[S][v] 为遍历状态S中的每一个节点,且最后到达S中的v的最小花费。
状态转移方程:dp[S][v] = min(dp[S][v],dp[S - {v}][u] + maps[u][v]).
我的代码:
#include<cstdio> #include<iostream> #define min(a,b) (a < b ? a : b) #define max(a,b) (a > b ? a : b) using namespace std; typedef __int64 LL; const LL inf = 0x3f3f3f3f; const int maxn = 15; LL n,maps[maxn][maxn]; LL dp[1<<maxn][maxn]; void floyd(){ for(int k = 0;k <= n; k++){ for(int i = 0;i <= n; i++){ for(int j = 0;j <= n; j++){ maps[i][j] = min(maps[i][j],maps[i][k] + maps[k][j]); } } } } void solve(){ int Ed = 1 << n,tmp; for(int S = 1 ; S < Ed ; S++) fill(dp[S],dp[S]+n+1,inf); for(int S = 1 ; S < Ed ; S++){ for(int v = 1; v <= n ; v++){ if(S >> (v - 1) & 1){ tmp = S & (~(1 << (v - 1))); if(tmp == 0){ dp[S][v] = maps[0][v]; continue; } for(int u = 1; u <= n ; u++){ if(tmp >> (u - 1) & 1) dp[S][v] = min(dp[S][v],dp[tmp][u] + maps[u][v]); } } } } LL res = inf; for(int v = 1; v <= n; v++){ res = min(res,dp[Ed-1][v] + maps[v][0]); } /*for(int S = 0;S < Ed; S++){ for(int i=1;i<=n;i++){ cout<<dp[S][i]<<" "; } cout<<endl; }*/ printf("%I64d\n",res); } int main(){ while(~scanf("%I64d",&n)){ if(n == 0) break; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) scanf("%I64d",&maps[i][j]); floyd(); solve(); } return 0; }
相关文章推荐
- 解决Linux MySQL报错ERROR 2002
- 程序烧写(使用SEGGER)
- nyoj 189 兔子的烦恼(一)(辗转相除法求最大公约数)
- K-Nearest Neighbors algorithm
- 【转载】JavaScript 经典实例收集整理
- Yii2学习笔记(一):Yii的安装和使用
- TabLayout、ViewPager和Fragment的多页面滑动
- mysql中为用户设置密码的多种方法
- 机器学习一些博客
- NowCoder猜想---统计n以内的素数个数
- JavaScript之this用法详解
- Android NDK编程浅入深出之--域和方法的操作
- Mysql数据库备份和还原常用的命令
- AVL Tree(平衡二叉树)
- 主流图片加载框架对比,及遇到的问题
- CListCtrl 虚拟列表显示复选框
- 1153 选择子序列
- ANE原生代码的调试(安卓)++flex通过ANE调试原生安卓代码
- hibernate基础之无法自动创建表总结
- grep与正则表达式