POJ 2686 Traveling by Stagecoach 【状压dp】

本文详细解析了POJ 2686题目的解题思路,采用动态规划结合图论的方法,通过二进制表示剩余票数状态,实现从任意点出发到所有可达点的最短时间计算,同时考虑了可能未完全使用票数的情况。

题目链接:http://poj.org/problem?id=2686

思路:

dp【二进制表示剩下的票】【v】; 

假设票有3张,那么最初始的状态是 dp[ 111 ] [ a ] = 0;尝试在三张中拿一张,然后从a点出发到所有能到的点,由此更新状态;

拿票的二进制操作时  S & ~(1 << i) , 把二进制数S中 第j个数变为0; 查看二进制数S第j个数是否是0的操作:(S & (1<<j)) > 0,要注意最外面的那个括号,因为这个括号卡了很久!!!!

还有要注意的是,最少的时间未必一定能把票用完,所以要把所有可能的情况,哪怕票还有都要查看一遍,选时间最少的那个;

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

using namespace std;

const double INF = 1e8;

double dp[1<<10][40];
int t[20], G[40][40];

int main (void)
{
	int n, m, p, a, b;
	while (scanf ("%d%d%d%d%d", &n, &m, &p, &a, &b) != EOF) {
		if (!n && !m && !p && !a && !b) break;
		for (int i = 0; i < n; ++i) scanf ("%d", &t[i]);
		memset (G, -1, sizeof (G));
		int u, v, w;
		for (int i = 0; i < p; ++i) {
			scanf ("%d%d%d", &u, &v, &w);
			G[u][v] = G[v][u] = w;
		}
		for (int i = 0; i < 1<<n; ++i)
			fill (dp[i], dp[i]+m+1, INF);

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

		for (int i = (1<<n)-1; i >= 0; --i) {
			ans = min (dp[i][b], ans);
			for (int v = 1; v <= m; ++v) {
				for (int j = 0; j < n; ++j) {
					if (i & (1<<j)) {
                        for (int u = 1; u <= m; ++u) {
                            if (G[u][v] >= 0 ) {
                                dp[i & ~(1<<j)][u] = min (dp[i & ~(1<<j)][u], dp[i][v] + (double)G[u][v]/t[j]);
                            }
                        }
					}
				}
			}
		}
		if (ans >= INF) printf ("Impossible\n");
		else printf ("%.3f\n", ans);
	}
	return 0;
 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值