程序员人生 网站导航

poj 3311 Hie with the Pie 状压dp

栏目:综合技术时间:2015-04-29 08:34:11
//参考了挑战程序设计第2版的tsp,dp[S][v]表示在已访问了集合S中的点情况下 //从动身访问剩下的节点并回到0号出发点的最少花费dp[V][0]都是0, //从0号节点回到0花费肯定是0, //dp[S][v] = min(dp[S|{u}][u]+d[v][u],dp[S][v]){u不在当前的集合中} //这样我们从[0,0]这个状态开始进行记忆化搜索,就1定能得到我们想要的答案 //对递推的做法,目前还有1丝的疑惑 //书上说对集合S(i)包括于S(j),就有i<=j; //solve3()中dp[S][v]表示当前在v点,还需访问S中的城市各1次后回到0处的最小花费 //初始的时候dp[0][i]=d[i][0],其他都为无穷大,状态转移方程为 //dp[S][v] = min(dp[S][v],dp[S-{j}][j]+d[i][j])(j属于S) //最后dp[S][0]就是我们要求的答案 //每种做法,各有千秋吧,仅以此题记念自己开启TSP之旅~继续练吧 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <functional> #include <iostream> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <stack> #include <vector> #define ceil(a,b) (((a)+(b)⑴)/(b)) #define endl ' ' #define gcd __gcd #define highBit(x) (1ULL<<(63-__builtin_clzll(x))) #define popCount __builtin_popcountll typedef long long ll; using namespace std; const int MOD = 1000000007; const long double PI = acos(⑴.L); template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; } template<class T> inline T lowBit(const T& x) { return x&-x; } template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; } template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; } const int maxn = 13; int d[maxn][maxn]; int dp[1 << maxn][maxn]; int n; const int inf = 0x3f3f3f3f; void init(){ n++; for (int i=0;i<n;i++) for (int j=0;j<n;j++) scanf("%d",&d[i][j]); } int dfs(int S,int v){ if (dp[S][v]>=0) return dp[S][v]; if (S==(1<<n)⑴&&v==0){ return dp[S][v]=0; } int res = inf; for (int u=0;u<n;u++) if (!((S>>u)&1)){ res = min(res,dfs(S|(1<<u),u)+d[v][u]); } return dp[S][v] = res; } void floyd(){ for (int k=0;k<n;k++) for (int i=0;i<n;i++) for (int j=0;j<n;j++) if (d[i][j]>d[i][k]+d[k][j]) d[i][j] = d[i][k]+d[k][j]; } void TSP(){ // for (int i=0;i<n;i++) dp[(1<<n)⑴][0]=0; for (int S=(1<<n)⑴;S>=0;S--) for (int i=0;i<n;i++) for(int u=0;u<n;u++) if (!((S>>u)&1)){ dp[S][i] = min(dp[S][i],dp[S|(1<<u)][u]+d[i][u]); } } void solve(){ memset(dp,⑴,sizeof(dp)); printf("%d ",dfs(0,0)); } void solve2(){ memset(dp,inf,sizeof(dp)); TSP(); printf("%d ",dp[0][0]); } void print(){ for (int i=0;i<(1<<n);i++){ for (int j=0;j<n;j++) printf("%d ",dp[i][j]); puts(""); } } void solve3(){ memset(dp,inf,sizeof(dp)); for (int i=0;i<n;i++) dp[0][i] = d[i][0]; for (int S=0;S<(1<<n);S++) for (int v=0;v<n;v++) for (int u=0;u<n;u++) if ((S>>u)&1) dp[S][v] = min(dp[S][v],dp[S^(1<<u)][u]+d[v][u]); //int res=inf; // print(); // for (int i=0;i<n;i++) // res = min(res,dp[i][0]); printf("%d ",dp[(1<<n)⑴][0]); } int main() { //freopen("G:Code1.txt","r",stdin); while(scanf("%d",&n)!=EOF){ if (!n) break; init(); floyd(); //solve(); //solve2(); solve3(); } return 0; }

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐