码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3311 Hie with the Pie 状压dp

时间:2015-04-08 21:37:26      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:poj   3311   hie with the pie   状压dp   

//参考了挑战程序设计第二版的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]这个状态开始进行记忆化搜索,就一定能得到我们想要的答案
//对于递推的做法,目前还有一丝的疑惑
//书上说对于集合S(i)包含于S(j),就有i<=j;
//solve3()中dp[S][v]表示当前在v点,还需访问S中的城市各一次后回到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)-1)/(b))
#define endl '\n'
#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(-1.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)-1&&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)-1][0]=0;
	for (int S=(1<<n)-1;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,-1,sizeof(dp));
	printf("%d\n",dfs(0,0));
}
void solve2(){
	memset(dp,inf,sizeof(dp));
	TSP();
	printf("%d\n",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\n",dp[(1<<n)-1][0]);
}
int main() {
    //freopen("G:\\Code\\1.txt","r",stdin);
	while(scanf("%d",&n)!=EOF){
		if (!n)
			break;
		init();
		floyd();
		
		//solve();
		//solve2();
		solve3();
	}
	return 0;
}

poj 3311 Hie with the Pie 状压dp

标签:poj   3311   hie with the pie   状压dp   

原文地址:http://blog.csdn.net/timelimite/article/details/44945919

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!