POJ2686 Traveling by Stagecoach(状压DP)

m个城市 n张车票 一个车票用一次 两条路径之间需要走长度除车票上马车数 求城市a到城市b的最快时间 不能到达就输出Impossible

dp[s][v] 现在在城市v, 剩下车票的集合为s。

《挑战程序设计》P195

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int INF = 0x5f5f5f5f;

const int M = 30;	// cities
const int N = 8;	// tickets

int n, m, p, a, b;
int t[N];
int d[M][M];
double dp[1 << N][M]; // dp[s][v] S:tickets, v:city

void solve()
{
	for (int i = 0; i < (1 << n); ++i)
		fill(dp[i], dp[i] + m, INF);
	dp[(1 << n) - 1][a - 1] = 0;
	double res = INF;
	for (int s = (1 << n) - 1; s >= 0; --s) {
		res = min(res, dp[s][b - 1]);

		for (int v = 0; v < m; ++v) {		// 选择一个城市出发
			for (int i = 0; i < n; ++i) {	// 选择一张车票
				if ((s >> i) & 1) {			// 如果车票在S中,即还没有使用
					for (int u = 0; u < m; ++u) {	// 选择一个城市到达
						if (d[v][u] >= 0) {	// 如果v,u之间有路径,s中减去车票i来到达u
							dp[s & ~(1 << i)][u] = min(dp[s & ~(1 << i)][u],
														dp[s][v] + (double)d[v][u] / t[i]);
						}
					}
				}
			}
		}
	}
	if (res == INF) printf("Impossible
");
	else printf("%.3f
", res);
}

int main()
{
    while (scanf("%d%d%d%d%d", &n, &m, &p, &a, &b) != EOF) {
		if (n == 0 && m == 0 && p == 0 && a == 0 && b == 0) break;
		for (int i = 0; i < n; ++i)
			scanf("%d", t + i);
		for (int i = 0; i < m; ++i)
			for (int j = 0; j < m; ++j)
				d[i][j] = -1;
		int x, y, z;
		for (int i = 0; i < p; ++i) {
			scanf("%d%d%d", &x, &y, &z);
			d[y - 1][x - 1] = d[x - 1][y - 1] = z;
		}

		solve();
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/wenruo/p/4752221.html