poj 3311 tsp入门

题意:n+1个点:0--n,找一条路径从0点出发遍历1--n的点再回到0,每个点可经过不止一次,求最短路径

裸的TSP问题,先用Floyd求出各个点之间最短路,再状压dp即可

用n+1位二进制表示状态

附模板:

 1 //首先不难想到用FLOYD先求出任意2点的距离dis[i][j]
 2 //接着枚举所有状态,用11位二进制表示10个城市和pizza店,1表示经过,0表示没有经过
 3 //定义状态DP(S,i)表示在S状态下,到达城市I的最优值
 4 //接着状态转移方程:DP(S,i) = min{DP(S^(1<<i-1),k) + dis[k][j],DP(S,i)},器重S^(1<<i-1)表示未到达城市i的所有状态,1<=k<=n
 5 //对于全1的状态,即S = (1<<n)-1则表示经过所有城市的状态,最终还需要回到PIZZA店0
 6 //那么最终答案就是min{DP(S,i) + dis[i][0]}
 7 //dij[i][j]:i到j最短路
 8
 9         for(int S = 0;S <= (1<<n)-1;++S)//枚举所有状态,用位运算表示
10             for(int i = 1;i <= n;++i)
11             {
12                 if(S & (1<<(i-1)))//状态S中已经过城市i
13                 {
14                     if(S == (1<<(i-1)))    dp[S][i] = dis[0][i];//状态S只经过城市I,最优解自然是从0出发到i的dis,这也是DP的边界
15                     else//如果S有经过多个城市
16                     {
17                         dp[S][i] = INF;
18                         for(int j = 1;j <= n;++j)
19                         {
20                             if(S & (1<<(j-1)) && j != i)//枚举不是城市I的其他城市
21                                 dp[S][i] = min(dp[S^(1<<(i-1))][j] + dis[j][i],dp[S][i]);
22                             //在没经过城市I的状态中,寻找合适的中间点J使得距离更短,和FLOYD一样
23                         }
24                     }
25                 }
26             }
27         ans = dp[(1<<n)-1][1] + dis[1][0];
28         for(int i = 2;i <= n;++i)
29             if(dp[(1<<n)-1][i] + dis[i][0] < ans)
30                 ans = dp[(1<<n)-1][i] + dis[i][0];
31         printf("%d/n",ans);

Code:

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 #define INF 1<<28;
 5 #define maxn 15
 6
 7 int a[maxn][maxn];
 8 int dp[1<<maxn][maxn];
 9 int ans,S,n;
10
11 int main()
12 {
13     ios::sync_with_stdio(false);
14     while (cin>>n)
15     {
16         memset(a,0,sizeof(a));
17         if (n==0)   break;
18         else
19         {
20             for (int i=0;i<=n;i++)
21                 for (int j=0;j<=n;j++)
22                     cin>>a[i][j];
23
24             for (int k=0;k<=n;k++)
25                 for (int i=0;i<=n;i++)
26                     for (int j=0;j<=n;j++)
27                     {
28                         if (a[i][k]+a[k][j]<a[i][j])
29                             a[i][j]=a[i][k]+a[k][j];
30                     }
31
32             for (int S=0;S<=(1<<n)-1;S++)
33                 for (int i=1;i<=n;i++)
34                 {
35                     if (S&(1<<(i-1)))
36                     {
37                         if (S==(1<<(i-1)))      dp[S][i]=a[0][i];
38                         else
39                         {
40                             dp[S][i]=INF;
41                             for (int j=1;j<=n;j++)
42                             {
43                                 if (S&(1<<(j-1))&&(j!=i))
44                                     dp[S][i]=min(dp[S^(1<<(i-1))][j] + a[j][i],dp[S][i]);
45                             }
46                         }
47                     }
48                 }
49
50             ans = dp[(1<<n)-1][1] + a[1][0];
51             for(int i = 2;i <= n;i++)
52                 if(dp[(1<<n)-1][i] + a[i][0] < ans)
53                     ans = dp[(1<<n)-1][i] + a[i][0];
54
55             cout<<ans<<endl;
56         }
57     }
58
59
60
61
62
63     return 0;
64 }

reference:

http://blog.csdn.net/chinaczy/article/details/5890768

时间: 2024-10-04 07:26:58

poj 3311 tsp入门的相关文章

POJ 3311 Hie with the Pie TSP+Floyd

保证每个点访问过一次就行,然后会到原点. 这种情况可以先做一边floyd,然后跑tsp就好. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque&g

poj 3311 经典tsp问题,状压dp

题目链接:Hie with the Pie 解题思路: Floyd + 状态压缩DP题意是有N个城市(1~N)和一个PIZZA店(0),要求一条回路,从0出发,又回到0,而且距离最短也就是TSP(旅行商)问题,首先不难想到用FLOYD先求出任意2点的距离dis[i][j]接着枚举所有状态,用11位二进制表示10个城市和pizza店,1表示经过,0表示没有经过定义状态DP(S,i)表示在S状态下,到达城市I的最优值接着状态转移方程:DP(S,i) = min{DP(S^(1<<i-1),k) +

poj 3311 Hie with the Pie 【旅行商+回原点】

题目:poj 3311 Hie with the Pie 题意:就是批萨点小二要送批萨,然后给你每个点的距离,有向的,然后让你就走一次回到原点的最短路. 分析:因为给出的是稠密图,所以要处理一下最短路,floyd 然后TSP就好. 枚举每个状态,对于当前状态的每一个已经走过的点,枚举是从那个点走过来的,更新最短路 状态:dp[st][i] :st状态下走到点 i 的最短路 转移方程:dp[st][i]=min(dp[st&~(1<<i)][j]+mp[j][i],dp[st][i]);

Hie with the Pie POJ - 3311

Hie with the Pie POJ - 3311 这题是类TSP,与TSP区别是可以重复经过节点,只需floyed预处理出指定两点间(走过任意数量点)的最短路即可. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int n,anss; 6 int dis[12][12]; 7 int ans[12][3000]; 8 int main()

POJ 3311 Hie with the Pie (状压DP)

状态压缩DP dp[i][j]表示在i状态(用二进制表示城市有没有经过)时最后到达j城市的最小时间 转移方程dp[i][j]=min(dp[i][k]+d[k][j],dp[i][j]) d[k][j]是k城市到j城市的最短距离 要先用flody处理 #include<bits.stdc++.h> using namespace std; int d[20][20],dp[1<<11][20]; int n,m; void flody() { for(int k=0;k<=n

Oil Deposits(poj 1526 DFS入门题)

http://poj.org/problem?id=1562 Oil Deposits Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12595   Accepted: 6868 Description The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp wor

Hie with the Pie (POJ 3311) 旅行商问题

昨天想练习一下状态压缩,百度搜索看到有博客讨论POJ 3311,一看就是简单的旅行商问题,于是快速上手写了状态压缩,死活样例都没过... 画图模拟一遍原来多个城市可以重复走,然后就放弃思考了... 刚刚把这个无聊的问题解决了,简单的Floyd+状压. 所谓Floyd算法,我在暑训的博客里提过,复杂度O(n3),但当时数据量太大不适合使用,这里刚好派上了用场. #include<cstdio> #include<iostream> #include<cstring> #i

[POJ 3311]Hie with the Pie——谈论TSP难题DP解决方法

主题连接:  id=3311">http://poj.org/problem?id=3311 题目大意:有n+1个点,给出点0~n的每两个点之间的距离,求这个图上TSP问题的最小解 思路:用二进制数来表示訪问过的城市集合.f[{S}][j]=已经訪问过的城市集合为S,訪问了j个城市.所需的最少花费. 这里提一下二进制数表示集合的方法(这里最好还是设集合中最多有n个元素): 假设集合S中最多会出现n个元素,则用长度为n的二进制数来表示集合S,每一位代表一个元素.该位为0表示该元素在集合S

[POJ 3311]Hie with the Pie——再谈TSP问题的DP解法

题目连接:  http://poj.org/problem?id=3311 题目大意:有n+1个点,给出点0~n的每两个点之间的距离,求这个图上TSP问题的最小解 思路:用二进制数来表示访问过的城市集合,f[{S}][j]=已经访问过的城市集合为S,访问了j个城市,所需的最少花费. 这里提一下二进制数表示集合的方法(这里不妨设集合中最多有n个元素): 如果集合S中最多会出现n个元素,则用长度为n的二进制数来表示集合S,每一位代表一个元素,该位为0表示该元素在集合S中不存在,为1表示该元素在集