POJ3311 Hie with the Pie(DP:TSP问题)
2016-06-05 15:49
351 查看
题意:
要到n个城市送披萨,每个城市只能经过一次,最后要回到原点,求最短路径。
要点:
经典的TSP问题,从0出发找到一条回路回到0,这就意味着可以回溯到前面的城市重新出发,这样就比较难。基本上可以想到先用Floyd算法求出每两个点的最短路径,然后就是DP,定义一个d[i][s]数组,表示当前在第i个城市,已经经过了s集合中的城市(包括i),s用二进制存储。
这样可以写出状态转移方程:d[i][s] = min(d[i][s], map[j][i] + d[j][s ^ (1 << (i - 1))]),在没经过城市I的状态中,寻找合适的中间点J使得距离更短,和Floyd一样。注意这题是有向图,i到j和j到i不一样。
要到n个城市送披萨,每个城市只能经过一次,最后要回到原点,求最短路径。
要点:
经典的TSP问题,从0出发找到一条回路回到0,这就意味着可以回溯到前面的城市重新出发,这样就比较难。基本上可以想到先用Floyd算法求出每两个点的最短路径,然后就是DP,定义一个d[i][s]数组,表示当前在第i个城市,已经经过了s集合中的城市(包括i),s用二进制存储。
这样可以写出状态转移方程:d[i][s] = min(d[i][s], map[j][i] + d[j][s ^ (1 << (i - 1))]),在没经过城市I的状态中,寻找合适的中间点J使得距离更短,和Floyd一样。注意这题是有向图,i到j和j到i不一样。
15591242 | Seasonal | 3311 | Accepted | 204K | 0MS | C++ | 1118B | 2016-06-05 15:23:23 |
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; const int inf = 100000000; int map[15][15],d[15][1<<11];//d(i,s)表示在第i个城已经访问s中的所有城市后返回0的最小路径长度 int n; void floyd()//先用Floyd算法算出所有最短路径 { for (int k = 0; k <= n; k++) for (int i = 0; i <= n; i++) for (int j = 0; j <= n; j++) if (map[i][j] > map[i][k] + map[k][j]) map[i][j] = map[i][k] + map[k][j]; } void dp() { int i, j, s; for (s = 0; s <= (1 << n)-1; s++) for (i = 1; i <= n; i++) if (s & 1 << (i - 1))//说明已经经过城市i { if (s == 1 << (i - 1))//此状态只要再经过i城市,所以直接从i回到0即可 d[i][s] = map[0][i]; else { d[i][s] = inf; for (j = 1; j <= n; j++) if (s & (1 << (j - 1)) && j != i)//对其他不是i的城市进行状态转移 d[i][s] = min(d[i][s], map[j][i] + d[j][s ^ (1 << (i - 1))]);//注意题目里i到j和j到i可能不一样,所以这里必须为j到i //在没经过城市i的状态中,寻找合适的中间点j使得距离更短,和floyd一样 } } int ans = inf; for (i = 1; i <= n; i++)//最后还要从i回到0 ans = min(d[i][(1 << n)-1] + map[i][0], ans); printf("%d\n", ans); } int main() { int i, j; while (scanf("%d", &n)&&n) { for (i = 0; i <= n; i++) for (j = 0; j <= n; j++) scanf("%d", &map[i][j]); floyd(); dp(); } return 0; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- C++动态规划之最长公子序列实例
- C++动态规划之背包问题解决方法
- 基于C++实现的各种内部排序算法汇总