1. 程式人生 > >[Luogu2991][USACO10OPEN]水滑梯Water Slides

[Luogu2991][USACO10OPEN]水滑梯Water Slides

ext 開心 log 故障 int 無法 格式 亮點 name

題面戳我
題面描述
受到秘魯的馬丘比丘的新式水上樂園的啟發,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選擇了在最壞情況下,最大化她的開心值,那麽,她在這種情況下一次沖浪可以得到的最大開心值是多少?
輸入輸出格式
輸入格式:
Line 1: Three space separated integers: V, E, and K
Lines 2..E + 1: Line i+1 contains three space separated integers: P_i, Q_i, and F_i
輸出格式:
Line 1: A single line with a single integer that is the minimum fun that Bessie can guarantee she can have.
輸入輸出樣例
輸入樣例#1:

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

輸出樣例#1:

9 

題解

DP+記搜轉移。
記dp[k][u]表示現在在u點至多還會發生k次錯誤,到達終點的最大開心值之和。轉移:(設v表示u能夠到達的點,len(u,v)表示兩點間的)
dp[k][u]=max(dp[k][v]+len(u,v));//沒出故障
dp[k][u]=min(dp[k-1][v]+len(u,v));//出了故障

最終的結果既然是最壞情況下就應該是兩式結果取min,註意當k=0時就沒有第二個表達式了。
最終答案為dpK,邊界條件是dp[0..K][n]=0。

code

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int N = 50005;
const int M = 150005;
struct edge{int to,next;ll w;}a[M];
int n,m,K,u,v,head[N],cnt;
ll w,dp[11][N];
ll dfs(int k,int u)
{
    if (dp[k][u]) return dp[k][u];
    for (int e=head[u];e;e=a[e].next)
        dp[k][u]=max(dp[k][u],dfs(k,a[e].to)+a[e].w);
    if (k)
        for (int e=head[u];e;e=a[e].next)
            dp[k][u]=min(dp[k][u],dfs(k-1,a[e].to)+a[e].w);
    return dp[k][u];
}
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    for (int i=1;i<=m;i++)
        scanf("%d%d%lld",&u,&v,&w),a[++cnt]=(edge){v,head[u],w},head[u]=cnt;
    return printf("%lld\n",dfs(K,1)),0;
}

[Luogu2991][USACO10OPEN]水滑梯Water Slides