hdu3001(三进制状态压缩DP)
2014-05-22 00:23
381 查看
这题和TSP(旅行售货员问题)本质区别是每个地方可以访问两下,而TSP只能访问一次,一开始题目读错了,用搜索来做结果wa了
后来看了解题,这个问题要用状态压缩来解。
题意:访问n个点,并且每个点最多访问两次,求最小费用
这里因为n较小,所以可以用状态压缩,每个点最多访问两次,所以要用三进制的状态压缩
解题思路:dp[i][S]表示当前状态为S,在i点;状态转移方程:dp[i][s] = min(dp[j][s1]+dist[i][j]),其中S表示含有i的状态,s1是新状态,s->s1,加了i到j的一条边
代码如下(附注释)
后来看了解题,这个问题要用状态压缩来解。
题意:访问n个点,并且每个点最多访问两次,求最小费用
这里因为n较小,所以可以用状态压缩,每个点最多访问两次,所以要用三进制的状态压缩
解题思路:dp[i][S]表示当前状态为S,在i点;状态转移方程:dp[i][s] = min(dp[j][s1]+dist[i][j]),其中S表示含有i的状态,s1是新状态,s->s1,加了i到j的一条边
代码如下(附注释)
#include<iostream> #include<algorithm> #include<cstring> #include<stack> #include<queue> #include<set> #include<map> #include<stdio.h> #include<stdlib.h> #include<ctype.h> #include<time.h> #include<math.h> #define N 15 #define inf 0x7fffffff #define eps 1e-9 #define pi acos(-1.0) #define P system("pause") using namespace std; int n; int fac ={1,3,9,27,81,243,729,2187,6561,19683,59049};//3的0次到9次 int dist ,dp [60000],state[60000] ;//dist[]记录输入信息; //dp[i][S]代表状态为S,且处于i点的最小费用;state[S][i]状态为S的三进制形式的第i位++的数字是多少(0,1,2) void init() { int i; memset(state,0,sizeof(state)); for(i = 0; i < fac[10]; i++)//计算状态S的三进制形式中每一位的数字,但记录的方向是反向的 { int k = 0, temp = i; while(temp) { state[i][k++] = temp % 3; temp /= 3; } } } int is_ok(int k)//判断不存在一位是0 { int ans = 0; while(k) { if(k%3 == 0) return 0; k /= 3; ans++; } return ans; } int main() { //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); // for(int i = 0; i < 10 ; i++) // cout<<fac[i]<<" "; init(); int m; while(scanf("%d%d",&n,&m) != EOF) { int i,j,k; int x,y,z; memset(dist,-1,sizeof(dist)); while(m--)//数据输入 { scanf("%d%d%d",&x,&y,&z); x--; y--; if(dist[x][y] == -1 || dist[x][y] > z) dist[x][y] = dist[y][x] = z; } memset(dp,-1,sizeof(dp)); for(i = 0; i < n; i++) dp[i][fac[i]] = 0; for(i = 0; i < fac ; i++) for(j = 0; j < n; j++) //dp[j][i],在i状态中加入一个结点 if(state[i][j] != 0 && dp[j][i] != -1) for(k = 0; k < n; k++) { if(dist[j][k] != -1 && j != k && state[i][k] < 2) { int ans = i + fac[k]; if(dp[k][ans] == -1) dp[k][ans] = dp[j][i] + dist[j][k]; else dp[k][ans] = min(dp[k][ans],dp[j][i] + dist[j][k]); //cout<<"fds"<<endl; } } int res = inf; for(i = 1; i < fac ; i++) { int k = is_ok(i); for(j = 0; j < n; j++) if(k != -1 && k == n) if(dp[j][i] != -1 && dp[j][i] < res) res = dp[j][i]; } if(res == inf) printf("-1\n"); else printf("%d\n",res); } // P; return 0; }
相关文章推荐
- hdu3001(三进制状态压缩dp)
- (复习)(转)03进制状态压缩DP——HDU3001 Travelling 旅行商问题
- 三进制状态压缩DP(旅行商问题TSP)HDU3001
- hdu3001(3进制状态压缩dp)
- hdu3001 Traveling (三进制状态压缩dp)
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- hdu3001(状态压缩dp)
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- HDU3001——Travelling(状态压缩DP)
- 状态压缩DP总结【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- hdu3001(状态压缩dp,三进制!)
- hdu3001 Travelling(状态压缩dp,三进制)
- HDU 3001 Travelling (三进制状态压缩DP+BFS)
- 3进制状态压缩DP——HDU3001 Travelling 旅行商问题
- hdu3001 Travelling 旅行商问题 状态压缩DP
- HDU3001(KB2-J 状态压缩dp)
- 状态压缩DP总结【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】
- hdu3001 Travelling 三进制状态压缩dp
- HDU 3001 Travelling (三进制状态压缩 DP)
- 三进制状态压缩DP(旅行商问题TSP)HDU3001