gfoj 樹形dp “訪問”術館
阿新 • • 發佈:2018-12-16
經過數月的精心準備,Peer Brelstet,一個出了名的盜畫者,準備開始他的下一個行動。藝術館的結構,每條走廊要麼分叉為兩條走廊,要麼通向一個展覽室。Peer知道每個展室裡藏畫的數量,並且他精確測量了通過每條走廊的時間。由於經驗老到,他拿下一幅畫需要5秒的時間。你的任務是編一個程式,計算在警察趕來之前,他最多能偷到多少幅畫。
第1行是警察趕到的時間,以s為單位。第2行描述了藝術館的結構,是一串非負整數,成對地出現:每一對的第一個數是走過一條走廊的時間,第2個數是它末端的藏畫數量;如果第2個數是0,那麼說明這條走廊分叉為兩條另外的走廊。資料按照深度優先的次序給出,請看樣例。
一個展室最多有20幅畫。通過每個走廊的時間不超過20s。藝術館最多有100個展室。警察趕到的時間在10min以內。其中30%的資料展室最多有18間
看似複雜,實則樹形dp
前面處理好就可以了
輸入真滴噁心。。。
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <stack> using namespace std; struct node { int x,y; }; struct node1 { int x,len; }; int t; stack <node> s; vector<node1> M[1000+5]; int f[1000+5][600+5],a[1000+5]; void dfs(int x) { int i,j,k; node1 n1; if (M[x].size()==0) for (i=0;i<=a[x];i++) f[x][i*5]=i; for (i=0;i<M[x].size();i++) { n1=M[x][i]; dfs(n1.x); for (j=t;j>=0;j--) for (k=0;k<=j-2*n1.len;k++) f[x][j]=max(f[x][j],f[x][j-2*n1.len-k]+f[n1.x][k]); } } int main() { int i,x,y,i1,fa,ans; node n1,n2; node1 n11; freopen("a.txt","r",stdin); scanf("%d",&t); i1=0; fa=0; while (1) { i1++; scanf("%d%d",&x,&a[i1]); n11.x=i1; n11.len=x; M[fa].push_back(n11); if (a[i1]==0) { n1.x=i1; n1.y=1; s.push(n1); fa=i1; } else { if (s.empty()) break; n2=s.top(); n2.y++; while (n2.y>2) { s.pop(); if (s.empty()) break; n2=s.top(); n2.y++; } if (s.empty()) break; s.pop(); s.push(n2); fa=n2.x; } } memset(f,0,sizeof(f)); dfs(0); ans=0; for (i=0;i<t;i++) ans=max(ans,f[0][i]); printf("%d\n",ans); return 0; }