POJ 2686 状态压缩DP

大致题意

有m座城市,城市间有p条道路,商人持有n张车票,(张车票对应相应的马匹数为 ti),需要从城市a前往城市b。两个直接相连城市花费时间为道路长度除以车票对应马匹数。求所需最小时间,不可达输出"Impossible"。1<=n<=8, 2<=m<=30。

考虑 “现在所余车票集合S,目前位于城市v” 的状态,n范围较小,S使用状态压缩方法表示。记忆化搜索求解。

#include <cstdio>
#include <STDLIB.H>
#include <cmath>
#include <iostream>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define eps 1e-4
#define M_PI 3.14159265358979323846
#define MAX_M 30
#define MAX_N 8
using namespace std;
int N, M, P, A, B;
int T[MAX_N], cost[MAX_M][MAX_M];
double dp[1 << MAX_N][MAX_M];

void init(){
	--A, --B;
	for(int i = 0; i < N; i++) scanf("%d", T + i);
	memset(cost, -1, sizeof(cost));
	for(int i = 0; i < P; i++){
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		--x, --y;
		cost[x][y] = z, cost[y][x] = z;
	}
}
double rec(int S, int v){
	if(dp[S][v] > -1) return dp[S][v];
	if(v == B) return dp[S][v] = 0.0;
	double res = INF;
	for(int u = 0; u < M; u++){
		if(cost[v][u] == -1) continue;
		for(int t = 0; t < N; t++){
			if(!(S >> t & 1)){
				int next = S | 1 << t;
				if(next == (1 << MAX_N) - 1 && u != B) continue;
				res = min(res, rec(next, u) + (double)cost[v][u] / T[t]);
			}
		}
	}
	return dp[S][v] = res;
}
void solve(){
	for(int i = 0; i < 1 << MAX_N; i++){
		for(int j = 0; j < MAX_M; j++) dp[i][j] = -1;
	}
	double res = min(INF, rec(0, A));
	if(res == INF) printf("Impossible\n");
	else printf("%.3f\n", res);
}
int main(){
	while(~scanf("%d%d%d%d%d", &N, &M, &P, &A, &B) && N){
		init();
		solve();
	}
	return 0;
}
发布了6 篇原创文章 · 获赞 0 · 访问量 47

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/104350657