poj 2686 Traveling by Stagecoach ---状态压缩DP

题意:给出一个简单带权无向图和起止点,以及若干张马车车票,每张车票可以雇到相应数量的马。
点 u, v 间有边时,从 u 到 v 或从 v 到 u 必须用且仅用一张车票,花费的时间为 w(u, v) / ticket[i],
其中 w(u, v) 表示边的权值,ticket[i] 表示第 i 张车票可以雇到的马匹数。求从起点到终点花费的最小时间。

如果不能到达终点,输出“Impossible”。(点数 <= 30,票数 <= 8)*/ 

http://poj.org/problem?id=2686

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const double INF=10000000000.0;
const int MAX_N=8;
const int MAX_M=30;
double weight[MAX_M][MAX_M];
double ticket[MAX_N];
int n,m,p,a,b;
double dp[1<<MAX_N][MAX_M];
void solve(){
	for(int i=0;i< 1<<n; i++){
		fill(dp[i],dp[i]+m,INF);
	}
	dp[0][a-1]=0; // 状态 dp[i][j]:= 使用车票为 i 到达城市 j 所需要的最小花费 
	for(int i=0;i< 1<<n;i++){
		for(int j=0;j<n;j++){
			if(i&(1<<j)) continue; //第j张车票已经使用 
			for(int k=0;k<m;k++){
				for(int v=0;v<m;v++){
					if(weight[k][v]>=0){ // 使用车票i 从 k 移动到 v 
						dp[i|(1<<j)][v]=min(dp[i|(1<<j)][v],dp[i][k]+weight[k][v]/ticket[j]); 
					}
				}
			}
		}
	}
	double res=INF;
	for(int i=0;i< 1<<n;i++) res=min(res,dp[i][b-1]);
	if(res==INF) cout<<"Impossible"<<endl;
	else printf("%.3lf
",res);
}
int main(){
	while(cin>>n>>m>>p>>a>>b){
		if(n+m+p+a+b==0)break;
		for(int i=0;i<n;i++) cin>>ticket[i];
		memset(weight,-1,sizeof(weight));  // -1表示没有边 
		for(int i=0;i<p;i++){
			int x,y,z;
			cin>>x>>y>>z;
			x--;y--;
			weight[x][y]=z;
			weight[y][x]=z;
		}
		solve();
	}
	return 0;
}


原文地址:https://www.cnblogs.com/pangblog/p/3275540.html