HDU 4114 Disney's FastPass

Disney's FastPass

Problem Description

Disney's FastPass is a virtual queuing system created by the Walt Disney Company. First introduced in 1999 (thugh the idea of a ride reservation system was first introduced in world fairs), Fast-Pass allows guests to avoid long lines at the attractions on which the system is installed, freeing them to enjoy other attractions during their wait. The service is available at no additional charge to all park guests.
--- wikipedia



Disneyland is a large theme park with plenties of entertainment facilities, also with a large number of tourists. Normally, you need to wait for a long time before geting the chance to enjoy any of the attractions. The FastPass is a system allowing you to pick up FastPass-tickets in some specific position, and use them at the corresponding facility to avoid long lines. With the help of the FastPass System, one can arrange his/her trip more efficiently.
You are given the map of the whole park, and there are some attractions that you are interested in. How to visit all the interested attractions within the shortest time?
 

Input

The first line contains an integer T(1<=T<=25), indicating the number of test cases.
Each test case contains several lines.
The first line contains three integers N,M,K(1 <= N <= 50; 0 <= M <= N(N - 1)/2; 0 <= K <= 8), indicating the number of locations(starting with 1, and 1 is the only gate of the park where the trip must be started and ended), the number of roads and the number of interested attractions.
The following M lines each contains three integers A,B,D(1 <= A,B <= N; 0 <= D <= 10^4) which means it takes D minutes to travel between location A and location B.
The following K lines each contains several integers Pi, Ti, FTi,Ni, Fi,1, Fi,2 ... Fi,Ni-1, FiNi ,(1 <= Pi,Ni, Fi,j <=N, 0 <= FTi <= Ti <= 10^4), which means the ith interested araction is placed at location Pi and there are Ni locations Fi,1; Fi,2 ... Fi,Ni where you can get the FastPass for the ith attraction. If you come to the ith attraction with its FastPass, you need to wait for only FTi minutes, otherwise you need to wait for Ti minutes.
You can assume that all the locations are connected and there is at most one road between any two locations.
Note that there might be several attrractions at one location.
 

Output

For each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y is the minimum time of the trip.
 

Sample Input

2
4 5 2
1 2 8
2 3 4
3 4 19
4 1 6
2 4 7
2 25 18 1 3
4 12 6 1 3
4 6 2
1 2 5
1 4 4
3 1 1
3 2 1
3 4 1
2 4 10
2 8 3 1 4
4 8 3 1 2
 

Sample Output

Case #1: 53
Case #2: 14
 

Source

 
题意:给出一张n个点,m条双向边的图。规定要游览的景点有k个,且在这些景点上会滞留一段时间。对于每一个景点有fastpass条件,当游览了此景点规定的其中任意一个地点时,经过该景点就可以用fastpass的时间,否则用更长的原时间。问从1出发,游览完所有k个景点再回到1最少用时是多少?
 
题解:要用时最少,游览的景点个数又不多,我们可以用最短路+状压DP来解决此题。
由于解题时各种不同的点对的最短路都有可能被用到,于是我们可用Floyd法把所有点对的最短路先O(n3)处理出来。
接下来就是状压了。这题的状压方程比一般的题稍微复杂一些。因为对于当前所处的状态,不仅要考虑已经游览了哪些景点,还要考虑当前已经拿到了多少景点的fastpass。
于是我们用f[i][s1][s2]表示现在到第i个点,s1表示拿到了哪些景点的fastpass,s2表示已经游览了多少景点。
则分两种情况转移,分别是对于规定必须游览的景点和所有点。
当s2的二进制位都满1,说明游览完成。此时枚举点i,加上从第i个点到第1个点的最短路表示返回。最后取最小值即可。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=55;
 4 int ca,T,n,m,K,x,y,z,num,p[8],t[8],ft[8],pass[N],e[N][N],f[N][1<<8][1<<8];
 5 void Floyd()
 6 {
 7     for (int k=1;k<=n;++k)
 8     for (int i=1;i<=n;++i)
 9     for (int j=1;j<=n;++j)
10     if (i!=j&&j!=k&&k!=i)
11     e[i][j]=min(e[i][j],e[i][k]+e[k][j]);
12 }
13 int solve()
14 {
15     int ans=1e9;
16     f[1][0][0]=0;
17     for (int s1=0;s1<(1<<K);++s1)
18     for (int s2=0;s2<(1<<K);++s2)
19     for (int i=1;i<=n;++i)
20     {
21         int now=f[i][s1][s2];
22         if (now>=1e9) continue;
23         if (s2==((1<<K)-1)) ans=min(ans,now+e[i][1]);
24         for (int j=0;j<K;++j)
25         if ((s2&(1<<j))==0)
26         {
27             int add=e[i][p[j]];
28             if (s1&(1<<j)) add+=ft[j];
29             else add+=t[j];
30             f[p[j]][s1|pass[p[j]]][s2|(1<<j)]=min(f[p[j]][s1|pass[p[j]]][s2|(1<<j)],now+add);
31         }
32         for (int j=1;j<=n;++j)
33         {
34             int add=e[i][j];
35             f[j][s1|pass[j]][s2]=min(f[j][s1|pass[j]][s2],now+add);
36         }
37     }
38     return ans;
39 }
40 int main()
41 {
42     scanf("%d",&T);
43     while (T--)
44     {
45         scanf("%d%d%d",&n,&m,&K);
46         memset(f,60,sizeof(f));
47         memset(e,60,sizeof(e));
48         memset(pass,0,sizeof(pass));
49         for (int i=1;i<=n;++i) e[i][i]=0;
50         for (int i=1;i<=m;++i)
51         {
52             scanf("%d%d%d",&x,&y,&z);
53             e[x][y]=e[y][x]=z;
54         }
55         Floyd();
56         for (int i=0;i<K;++i)
57         {
58             scanf("%d%d%d%d",&p[i],&t[i],&ft[i],&num);
59             for (int j=1;j<=num;++j)
60             {
61                 scanf("%d",&x);
62                 pass[x]|=1<<i;
63             }
64         }
65         printf("Case #%d: %d\n",++ca,solve());
66     }
67     return 0;
68 }
View Code

 

posted @ 2017-11-02 13:32  氟铷氡氦  阅读(272)  评论(2编辑  收藏  举报