码迷,mamicode.com
首页 > 其他好文 > 详细

北大ACM2686——Traveling by Stagecoach~~状态压缩DP

时间:2015-07-28 21:15:59      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:北大   acm   压缩   位运算   dp   

最近才看书,看到状态压缩。对于状态压缩DP,其实就是集合上的DP。

这需要我们了解一些位运算:

集合{0,1,2,3,....,n-1}的子集可以用下面的方法编码成整数

技术分享

像这样,一些集合运算就可以用如下的方法来操作:

1.空集....................0

2.只含有第i个元素的集合{i}................1 << i

3.含有全部n个元素的集合{0,1,2,3,....,n - 1}.............(1 << n) - 1

4.判断第i个元素是否属于集合S.................................if(S >> i & 1)

5.向集合中加入第i个元素S ∪ {i}...............................S | 1 << i

6.从集合中除去第i个元素S \ {i}..................................S & ~(1 << i)

7.集合S和T的并集S∪T...............................................S | T

8.集合S和T的交集S∩T................................................S & T


而题目的意思是:一个人在m个城市的国家旅行,他有n张车票,这个国家有p条路,一条路连接两个城市,他要从a城市到b城市,从一个城市到另一个城市所需要的时间是路的长度除以车票的面值,面值是多少表示可以有多少匹马来拉,求最短的时间。


这题,不能直接用最短路径的算法来求解,有车票的限制。我们将在第i个城市看作一个状态,剩下的车票为一个集合S,从这个城市出发,使用一张车票到达城市j,现在他在第j个城市,状态为S \ {i},花费的时间就是路的长度除以车票的面值。

下面的是 AC的代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const double INF = 10000000000.00;
int n, m, p, a, b;
int ticket[10];
int map[32][32];

double dp[1 << 10][32];

double min(double a, double b)   //取最小值
{
	return a > b ? b : a;
}

void solve()
{
	int i, j;
	for(i = 0; i < 1 << n; i++) //初始化dp数组
	{
		for(j = 0; j < 32; j++)
			dp[i][j] = INF;
	}
	dp[(1 << n) - 1][a - 1] = 0;
	double res = INF;
	for(int S = (1 << n) - 1; S >= 0; S--)  //集合S
	{
		res = min(res, dp[S][b - 1]);
		for(int v = 0; v < m; v++)
		{
			for(i = 0; i < n; i++)        //枚举车票
			{
				if(S >> i & 1)            //判断第i个车票是否属于集合S
				{
					for(int u = 0; u < m; u++)
					{
						if(map[v][u] >= 0) //城市v到u有路,使用第i个车票从v到u
						{
							dp[S & ~(1 << i)][u] = min(dp[S & ~(1 << i)][u], dp[S][v] + double(map[v][u]) / ticket[i]);
						}
					}
				}
			}
		}
	}
	if(res == INF)
		printf("Impossible\n");
	else
		printf("%.3lf\n", res);
}

int main()
{
//	freopen("data.txt", "r", stdin);
	int i, x, y, z;
	while(cin >> n >> m >> p >> a >> b)
	{
		memset(map, -1, sizeof(map));
		if(n == 0 && m == 0 && p == 0 && a == 0 && b == 0)
			break;
		for(i = 0; i < n; i++)   //输入数据
			cin >> ticket[i];
		for(i = 0; i < p; i++)
		{
			cin >> x >> y >> z;
			map[x - 1][y - 1] = z;
			map[y - 1][x - 1] = z;
		}
		solve();	
	}
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

北大ACM2686——Traveling by Stagecoach~~状态压缩DP

标签:北大   acm   压缩   位运算   dp   

原文地址:http://blog.csdn.net/qq_25425023/article/details/47109623

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!