您的位置:首页 > 其它

POJ_2686_Traveling by Stagecoach_状态压缩dp

2014-11-10 00:39 471 查看
我绝逼是做死小王子

题意:

一个土豪做马车旅行,他当前在s点,想到t点去,p条路和m个城市组成了一个无重边、无自环的无向图,土豪有n张票做马车,用一张少一张,第i票代表有t[i]匹马,做一辆马车走一条路须花费w/t的时间,问最少花费多少时间?

Input
The input consists of multiple datasets, each in the following format. The last dataset is followed by a line containing five zeros (separated by a space).

n m p a b

t1 t2 ... tn

x1 y1 z1

x2 y2 z2

...

xp yp zp

Every input item in a dataset is a non-negative integer. If a line contains two or more input items, they are separated by a space.

n is the number of coach tickets. You can assume that the number of tickets is between 1 and 8. m is the number of cities in the network. You can assume that the number of cities is between 2 and 30. p is the number of roads between cities, which may be zero.

a is the city index of the starting city. b is the city index of the destination city. a is not equal to b. You can assume that all city indices in a dataset (including the above two) are between 1 and m.

The second line of a dataset gives the details of coach tickets. ti is the number of horses specified in the i-th coach ticket (1<=i<=n). You can assume that the number of horses is between 1 and 10.

The following p lines give the details of roads between cities. The i-th road connects two cities with city indices xi and yi, and has a distance zi (1<=i<=p). You can assume that the distance is between 1 and 100.

No two roads connect the same pair of cities. A road never connects a city with itself. Each road can be traveled in both directions.

Output
For each dataset in the input, one line should be output as specified below. An output line should not contain extra characters such as spaces.

If the traveler can reach the destination, the time needed for the best route (a route with the shortest time) should be printed. The answer should not have an error greater than 0.001. You may output any number of digits after the decimal point, provided that
the above accuracy condition is satisfied.

If the traveler cannot reach the destination, the string "Impossible" should be printed. One cannot reach the destination either when there are no routes leading to the destination, or when the number of tickets is not sufficient. Note that the first letter
of "Impossible" is in uppercase, while the other letters are in lowercase.

思路很简单,把票的信息压缩即可,第二维代表当前所在点,状态转移即可。

问题是状态的遍历顺序。挑战上给了一个性质:对于两个数i,j,他们代表的集合S[i],S[j],如果S[i]属于S[j],则必有i<=j,刚才还不明白为什么,现在一想这很显然啊,把i和j变成二进制,然后如果S[i]属于S[j],那么i肯定比j小。

这样的话,如果我们把状态从大到小遍历,考虑每个当前状态,所有可以包括他的状态都比他大,因此也都已经被求出来了,这样只要二进制状态压缩的初始状态求出来了,用这个顺序遍历就肯定可以。

代码如下,double坑死爹了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define mxn 10
#define mxm 40
int n,m,a,b,p;
double horse[mxn];
double mapp[mxm][mxm];
double dp[1<<mxn][mxm];
void init(){
for(int i=0;i<m;++i)
for(int j=0;j<m;++j)
mapp[i][j]=-1;
for(int i=0;i<(1<<n);++i)
for(int j=0;j<m;++j)
dp[i][j]=-1;
}
int main(){
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("%lf",&horse[i]);
init();
for(int i=0;i<p;++i){
int u,v;
double w;
scanf("%d%d%lf",&u,&v,&w);
mapp[u-1][v-1]=mapp[v-1][u-1]=w;
}
double ans=-1;
dp[(1<<n)-1][a-1]=0.0;
for(int i=(1<<n)-1;i>=0;--i){
if(ans==-1)	ans=dp[i][b-1];
else if(dp[i][b-1]!=-1)	ans=min(ans,dp[i][b-1]);
for(int u=0;u<m;++u)	if(dp[i][u]!=-1)
for(int v=0;v<m;++v)	if(mapp[u][v]!=-1)
for(int j=0;j<n;++j)	if(i&(1<<j))
if(dp[i&(~(1<<j))][v]==-1)	dp[i&(~(1<<j))][v]=dp[i][u]+mapp[u][v]/horse[j];
else	dp[i&(~(1<<j))][v]=min(dp[i&(~(1<<j))][v],dp[i][u]+mapp[u][v]/horse[j]);
}
if(ans==-1)	puts("Impossible");
else	printf("%.3lf\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: