BZOJ1916[USACO 2010 Open Gold 2.Water Slides]——DP+记忆化搜索

题目描述

受到秘鲁的马丘比丘的新式水上乐园的启发,Farmer John决定也为奶牛们建 一个水上乐园。当然,它最大的亮点就是新奇巨大的水上冲浪。超级轨道包含 E (1 <= E <=150,000)条小轨道连接着V (V <= 50,000)个水池,编号为1..V。每个小轨道必须按照特定的方向运行,不能够反向运行。奶牛们从1号水池出发,经过若干条小轨道,最终到达V号水池。每个水池(除了V号和1号之外,都有至少一条小轨道进来和一条小轨道出去,并且,一头奶牛从任何一个水池到达V 号水池。最后,由于这是一个冲浪,从任何一个水池出发都不可能回到这个水池) 每条小轨道从水池P_i到水池Q_i (1 <= P_i <= V; 1<= Q_i <= V; P_i != Q_i), 轨道有一个开心值F_i (0 <= F_i <= 2,000,000,000),Bessie总的开心值就是经过的所有轨道的开心值之和。Bessie自然希望越开心越好,并且,她有足够长的时间在轨道上玩。因此,她精心地挑选路线。但是,由于她是头奶牛,所以,会有至多K (1 <= K <= 10)次的情况,她无法控制,并且随机从某个水池选择了一条轨道(这种情况甚至会在1号水池发生) 如果Bessie选择了在最坏情况下,最大化她的开心值,那么,她在这种情况下一次冲浪可以得到的最大开心值是多少? 在样例中,考虑一个超级轨道,包含了3个水池(在图中用括号表示)和4条小轨道,K的值为1 (开心值在括号外表示出来,用箭头标识)   她总是从1号水池出发,抵达3号水池。如果她总是可以自己选择,就是不会发生不能控制的情况她可以选择从1到2(这条轨道开心值为5),再从2到3(开心值为5),总的开心值为5+5=10。但是,如过她在1号水池失去控制,直接到了3,那么开心值为9,如果她在2号水池失去控制,她总的开心值为8。Bessie想要找到最大化开心值的方案,可以直接从1到3,这样,如果在1号水池失去控制,这样,她就不会在2号水池失去控制了,就能够得到10的开心值。因此,她的开心值至少为9

输入

* 第一行: 三个用空格隔开的整数: V, E, 和 K * 第2到第E+1行: 第i+1行包含三个用空格隔开的整数: P_i, Q_i, and F_i

输出

* 第一样: 一行一个整数表示在最坏情况下最大化的开心值

样例输入

3 4 1
2 3 5
1 2 5
1 3 9
2 3 3

样例输出

9
 
首先说一下问题的意思:“在最坏情况下最大化的开心值”就是指你想使她的开心值最小,但她想使开心值最大的最优策略。但你想阻止她的方法只有在k个节点阻止她走最长路方向,却不能指定她走哪条路。对于样例,最长路是从1到2再到3,长度为5+5=10。如果你在1节点阻止她,那她只能直接走到3,长度为9;如果你在2阻止她,并不是说她走到2再被阻止,走了长度为3的路,而是直接放弃走2,直接走到3,长度还是9。所以她至少获得的开心值是9。从1走到n等价于从n走到1,所以我们不妨倒着来做(正推比较麻烦但也可行),定义f[i][j]表示走到i节点还剩j次失误的最优解,最终结果就是f[1][0];f[x][j]=min(max(f[from[i]][j]+val[i]),min(f[from[i]][j-1]+val[i])),其中from[i]表示能直接到达x的一个点。从1节点记忆化搜索即可。
最后附上代码。
 1 #include<queue>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 int head[50010];
 9 int to[150010];
10 int next[150010];
11 long long val[150010];
12 int n,m,k;
13 int x,y;
14 long long v;
15 int tot;
16 long long f[50010][16];
17 long long INF=1ll<<60;
18 void add(int x,int y,long long v)
19 {
20     tot++;
21     next[tot]=head[x];
22     head[x]=tot;
23     to[tot]=y;
24     val[tot]=v;
25 }
26 long long dfs(int x,int y)
27 {
28     if(f[x][y]!=INF)
29     {
30         return f[x][y];
31     }
32     long long ma=0ll;
33     long long mi=INF;
34     for(int i=head[x];i;i=next[i])
35     {
36         ma=max(ma,dfs(to[i],y)+val[i]);
37         if(y+1<=k)
38         {
39             mi=min(mi,dfs(to[i],y+1)+val[i]);
40         }
41     }
42     return f[x][y]=min(mi,ma);
43 }
44 int main()
45 {
46     scanf("%d%d%d",&n,&m,&k);
47     for(int i=1;i<=m;i++)
48     {
49         scanf("%d%d%lld",&x,&y,&v);
50         add(x,y,v);
51     }
52     for(int i=1;i<=n;i++)
53     {
54         for(int j=0;j<=k;j++)
55         {
56             if(i!=n)
57             {
58                 f[i][j]=INF;
59             }
60             else
61             {
62                 f[i][j]=0;
63             }
64         } 
65     }
66     printf("%lld",dfs(1,0));
67 }
View Code

猜你喜欢

转载自www.cnblogs.com/Khada-Jhin/p/9135527.html