poj 3311 Hie with the Pie 狀壓dp
來源:程序員人生 發(fā)布時間:2015-04-29 08:34:11 閱讀次數(shù):3689次
//參考了挑戰(zhàn)程序設(shè)計第2版的tsp,dp[S][v]表示在已訪問了集合S中的點情況下
//從動身訪問剩下的節(jié)點并回到0號出發(fā)點的最少花費dp[V][0]都是0,
//從0號節(jié)點回到0花費肯定是0,
//dp[S][v] = min(dp[S|{u}][u]+d[v][u],dp[S][v]){u不在當(dāng)前的集合中}
//這樣我們從[0,0]這個狀態(tài)開始進行記憶化搜索,就1定能得到我們想要的答案
//對遞推的做法,目前還有1絲的疑惑
//書上說對集合S(i)包括于S(j),就有i<=j;
//solve3()中dp[S][v]表示當(dāng)前在v點,還需訪問S中的城市各1次后回到0處的最小花費
//初始的時候dp[0][i]=d[i][0],其他都為無窮大,狀態(tài)轉(zhuǎn)移方程為
//dp[S][v] = min(dp[S][v],dp[S-{j}][j]+d[i][j])(j屬于S)
//最后dp[S][0]就是我們要求的答案
//每種做法,各有千秋吧,僅以此題記念自己開啟TSP之旅~繼續(xù)練吧
#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;
}
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進行捐贈