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\n",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;

}


 

 

你可能感兴趣的:(poj)