1. 程式人生 > >[luogu 1270] “訪問”美術館 (樹形dp)

[luogu 1270] “訪問”美術館 (樹形dp)

2個 結果 pac 轉移 using lld space p12 多少

傳送門

Description

經過數月的精心準備,Peer Brelstet,一個出了名的盜畫者,準備開始他的下一個行動。藝術館的結構,每條走廊要麽分叉為兩條走廊,要麽通向一個展覽室。Peer知道每個展室裏藏畫的數量,並且他精確測量了通過每條走廊的時間。由於經驗老到,他拿下一幅畫需要5秒的時間。你的任務是編一個程序,計算在警察趕來之前,他最多能偷到多少幅畫。
技術分享圖片

Input

第1行是警察趕到的時間,以s為單位。第2行描述了藝術館的結構,是一串非負整數,成對地出現:每一對的第一個數是走過一條走廊的時間,第2個數是它末端的藏畫數量;如果第2個數是0,那麽說明這條走廊分叉為兩條另外的走廊。數據按照深度優先的次序給出,請看樣例。

一個展室最多有20幅畫。通過每個走廊的時間不超過20s。藝術館最多有100個展室。警察趕到的時間在10min以內。

Output

輸出偷到的畫的數量

Sample Input

60
7 0 8 0 3 1 14 2 10 0 12 4 6 2

Sample Output

2

Solution

dfs時記錄到這個節點最多剩多長時間
然後枚舉這個節點和它子節點(如果有的話)的消耗時間直接轉移即可
PS:本來想著做幾道做幾道比較水的樹形dp結果。。WA三次QAQ,查了半天代碼最後絕望去看題解發現由於要“在警察趕來之前”所以輸入的時間要-1。。,好吧是我太蠢了QAQ

Code

//By Menteur_Hxy
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
#define ls nd[x][0]
#define rs nd[x][1]
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;

int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-') f=-f; c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=110;
int T,tot=1;
int nd[N<<2][2],ti[N<<2],pi[N<<2],dp[N<<2][6010];

void build(int x) {
    ti[x]=read(),pi[x]=read();
    if(!pi[x]) ls=++tot,build(tot),rs=++tot,build(tot);
}

void dfs(int x,int t) {
    if(pi[x]) F(i,ti[x]*2+1,min(t,ti[x]*2+5*pi[x])) dp[x][i]=(i-ti[x]*2)/5;
    else if(t>ti[x]*2) {
        dfs(ls,t-ti[x]*2); dfs(rs,t-ti[x]*2);
        F(i,ti[x]*2+1,t) F(j,0,i-ti[x]*2) 
            dp[x][i]=max(dp[x][i],dp[ls][j]+dp[rs][i-ti[x]*2-j]);
    }
//  cout<<t<<endl;
//  F(i,1,t) if(dp[x][i]) printf("dp[%d][%d]=%d\n",x,i,dp[x][i]);
}

signed main() {
    scanf("%lld",&T);
    build(1);
    dfs(1,T);
    printf("%lld",dp[1][T-1]);//要-1 QAQ
    return 0;
}

[luogu 1270] “訪問”美術館 (樹形dp)