POJ3311 Hie with the Pie(DP:TSP问题)

来源:互联网 发布:如何备份iphone数据 编辑:程序博客网 时间:2024/06/05 08:09

题意:

要到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不一样。


15591242Seasonal3311Accepted204K0MSC++1118B2016-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回到0ans = 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;}


0 0
原创粉丝点击