您的位置:首页 > 其它

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

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回到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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 算法 dp poj 动态规划