Traveling by Stagecoach POJ - 2686 状压dp

题意:

n张票,m个点,p条路(双向),a起点,b终点

X1~Xn:票的权值,耗时=路长/票权

求从a到b的最短时间

思路:

状态压缩dp,dp[s][i]:s为编码后的含票状态,目前在i点,数组t[]存储票的权

转移方程:使用一张车票k到点j:dp[s\{k}][j]=min(dp[s][i]+map[j][i]/t[k],dp[s\{k}][j])

复杂度:o(2^n*n^2),状压一般都是小数据才能用吧。。TSP问题是NP困难的。。恩

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std;

#define maxn 10
#define maxm 33
#define maxp 910
#define inf 0x3f3f3f3f
int n, m, p, a, b;//n票,m点,p路

int map[maxm][maxm];
int t[maxn];
double dp[1<<maxn][maxm];//dp[S][v]:车票集合S,位于v

void solve() 
{
	for (int i = 0; i < (1 << n); i++) {
		fill(dp[i], dp[i] + m + 1, inf);
	}

	dp[(1 << n) - 1][a] = 0;

	double res = inf;
	for (int S = (1 << n) - 1; S >= 0; S--) {

		res = min(res, dp[S][b]);

		//cout << res << endl;
		for (int v = 1; v <= m; v++) {
			for (int i = 0; i < n; i++) {
				if (S >> i & 1) {
					for (int u = 1; u <= m; u++) {
						if (map[u][v] > 0) {

							dp[S & ~(1 << i)][u] = min(dp[S & ~(1 << i)][u], dp[S][v] + (double)map[v][u] / t[i]);
							//cout << dp[S & ~(1 << i)][u] << endl;
						}
					}
				}
			}
		}
	}
	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) {
		
		memset(map, -1, sizeof(map));

		for (int i = 0; i < n; i++) {
			scanf("%d", &t[i]);
		}

		for (int i = 1; i <= p; i++) {
			int u, v, w;
			scanf("%d %d %d", &u, &v, &w);
			map[u][v] = map[v][u] = w;
		}
		solve();
	}
}

memset写成sizeof(-1)调试了好久。。

一开始写map[u][v]判通畅还写的大于等于。。

好巧啊,所有样例出来全是0

posted @ 2017-02-16 01:25  Drenight  阅读(90)  评论(0编辑  收藏  举报