标签:dp
题目链接:点击打开链接
题意:大致就是邮递员要从0号 送快件,一共有n个地方,要求从0开始走完所有的节点在回到0的最短路径。先用Floyd跑出来最短路,然后就是一个裸TSP问题了
TSP:顾名思义,旅行商问题,就是从起点出发遍历n个城市在回到起点的最短路径,在n比较小的情况下状压是个比较好的办法,二进制0代表没访问该城市,反之亦然。所以一共有 2^n-1种状态, 设 dp[s][i] 代表当前状态为s 当前所在城市节点为i dp[s][i]=min(dp[s][i] ,dp[s‘][j]+dis[j][i]) (从当前状态中去掉i 然后从其他的已经访问过的节点中更新dp[s][i])
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cctype> #include <vector> #include <deque> #include <queue> #include <set> #include <map> #define INF 0x3f3f3f3f #define maxn 1<<11 #define Mod 1000000007 #define ll long long #define _ll __int64 #define ull unsigned long long using namespace std; int n,dis[15][15],dp[maxn][15]; void Floyd() { for(int k=0; k<=n; k++) for(int i=0; i<=n; i++) for(int j=0; j<=n; j++) dis[i][j]=min(dis[i][j],dis[i][k] +dis[k][j]); } void solve() { int tot=(1<<n)-1; for(int s=0; s<=tot; s++) { for(int i=1; i<=n; i++) { if(s&(1<<(i-1))) { if(s==(1<<(i-1))) dp[s][i]=dis[0][i]; else { dp[s][i]=INF; for(int j=1; j<=n; j++) if(s&(1<<(j-1)) && j!=i) dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+dis[j][i]); } } } } int ans=INF; for(int i=1; i<=n; i++) ans=min(ans,dp[tot][i]+dis[i][0]); printf("%d\n",ans); } int main() { while(~scanf("%d",&n)&&n) { for(int i=0; i<=n; i++) for(int j=0; j<=n; j++) scanf("%d",&dis[i][j]); Floyd(); solve(); } return 0; }
POJ 3311-Hie with the Pie(最短路+状压DP)
标签:dp
原文地址:http://blog.csdn.net/qq_16255321/article/details/41778281