HDU 4616 Game

來源:互聯網
上載者:User

樹形DP

題意:給一棵樹,樹上的每個節點會有財富,某些節點會有陷阱,現在你可以從任意節點開始走,不能往回走,碰到第C個陷阱就停,問能獲得的最大價值。

思路:開三維狀態,分別是【當前節點】【已經遇到的陷阱數】【是否從陷阱開始】,值表示從這個節點的子節點在相應情況下能取得的最大值。那麼最長的那條路必然是由兩棵子樹的最大值合并而成或者就是從這個節點到子樹的某處的價值。

需要注意的是合并時候的情況。當遇到的陷阱樹小於C的時候,兩條子路可以任意取,而當遇到的陷阱數等於C的時候,只能是以一個陷阱處結束這種情況(當筆者寫完這句話的時候,突然發現這丫就是個大水題啊,卡兩天這智商是什麼情況T_T)

然後就是取子路的時候注意不能取到同一棵子樹,所以需要儲存最大和次大兩個價值以及它們來自的節點

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define clr(a,b) memset((a),(b),sizeof(a))int max(int a, int b) { return a>b?a:b; }int min(int a, int b) { return a<b?a:b; }const int MAXN = 50010;int trap[MAXN],w[MAXN];int m1[MAXN][6][2],m2[MAXN][6][2];int rt1[MAXN][6][2],rt2[MAXN][6][2];int head[MAXN],tot;struct E{int v, next;}edge[MAXN<<1];int n,C;int ans ;int cal(int u,int i,int k,int j, int r){int ret = m1[u][i][k] + w[u];if(rt1[u][i][k] == rt1[u][j][r]) ret += m2[u][j][r];else ret += m1[u][j][r];int ret2 = m1[u][j][r] + w[u];if(rt1[u][i][k] == rt1[u][j][r]) ret2 += m2[u][i][k];else ret2 += m1[u][i][k];return max(ret,ret2);}void dfs(int u, int fa){int p,i,j,k,r,temp;for(p=head[u]; p!=-1; p=edge[p].next){int v = edge[p].v;if(v == fa) continue;dfs(v,u);for(i=0; i<=C; i++){for(k=0; k<2; k++){if(m1[v][i][k] > m2[u][i][k]){m2[u][i][k] = m1[v][i][k];rt2[u][i][k] = v;if(m1[u][i][k] < m2[u][i][k]){swap(m1[u][i][k], m2[u][i][k]);swap(rt1[u][i][k], rt2[u][i][k]);}}}}}//計算等於C的情況for(i=0; i<=C; i++){j = C-trap[u]-i;if(j <= 0) break;for(k=0; k<2; k++){temp = cal(u,i,k,j,1);if(temp > ans) ans = temp;}}// 計算小於C的情況for(i=0; i<=C; i++){for(j=0; j<=C; j++){if(i+j+trap[u] >= C) break;for(k=0; k<2; k++){for(r=0; r<2; r++){temp = cal(u,i,k,j,r);if(temp > ans) ans = temp;}}}}if(trap[u]){for(i=C-1; i>=0; i--){m1[u][i+1][1] = m1[u][i][1] + w[u];if(m1[u][i][0]) m1[u][i+1][0] = m1[u][i][0] + w[u], m1[u][i][0] = 0;}m1[u][1][1] = w[u];m1[u][0][1] = 0;}else{for(i=C; i>=0; i--){m1[u][i][0] += w[u];if(m1[u][i][1]) m1[u][i][1] += w[u];}}ans = max(ans, m1[u][C][1]);if(trap[u]) ans = max(ans, m1[u][C][0]);for(i=0; i<C; i++){for(k=0; k<2; k++){ans = max(ans, m1[u][i][k]);}}}void init(){clr(m1,0);clr(m2,0);clr(rt1,-1);clr(rt2,-1);clr(head,-1);tot = 0;ans = -1;}void add_edge(int a, int b){edge[tot].next = head[a];edge[tot].v = b;head[a] = tot ++;}int main(){int cas;int a,b;int i;scanf("%d", &cas);while(cas--){scanf("%d%d", &n, &C);init();for(i=0; i<n; i++){scanf("%d%d", &w[i], &trap[i]);ans = max(ans, w[i]);}for(i=0; i<n-1; i++){scanf("%d%d", &a, &b);add_edge(a,b);add_edge(b,a);}dfs(0,-1);printf("%d\n", ans);}return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.