【poj2486】【Apple Tree】【樹形dp】

來源:互聯網
上載者:User

標籤:

Apple Tree

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7893 Accepted: 2642
Description

Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of apples. Wshxzt starts her happy trip at one node. She can eat up all the apples in the nodes she reaches. HX is a kind guy. He knows that eating too many can make the lovely girl become fat. So he doesn’t allow Wshxzt to go more than K steps in the tree. It costs one step when she goes from one node to another adjacent node. Wshxzt likes apple very much. So she wants to eat as many as she can. Can you tell how many apples she can eat in at most K steps.
Input

There are several test cases in the input
Each test case contains three parts.
The first part is two numbers N K, whose meanings we have talked about just now. We denote the nodes by 1 2 … N. Since it is a tree, each node can reach any other in only one route. (1<=N<=100, 0<=K<=200)
The second part contains N integers (All integers are nonnegative and not bigger than 1000). The ith number is the amount of apples in Node i.
The third part contains N-1 line. There are two numbers A,B in each line, meaning that Node A and Node B are adjacent.
Input will be ended by the end of file.

Note: Wshxzt starts at Node 1.
Output

For each test case, output the maximal numbers of apples Wshxzt can eat at a line.
Sample Input

2 1
0 11
1 2
3 2
0 1 2
1 2
1 3
Sample Output

11
2

題解:這道題我開始想的是用f[i][j]表示在i節點的時候已經走了j步時的取到的最多的蘋果數。但是我發現這樣做對於兩個在不同子樹中節點的LCA到根節點的這一段距離會重複計算。
所以我們把需要動規方程所表示的狀態換一下:f[i][j]表示到節點i的時候在i的子樹中已經走了j步時的取到的最多的蘋果。
我們再考慮怎樣用子樹去更新:因為這樣的情況比較多,所以我們可以考慮用背包來解決這個問題。
但是我們需要注意一個問題:那就是題目中說可能會走到一個節點以後就不再往回走了,對於這種問題,我們還需要在改進一下動規方程:f[i][j][0]表示到節點i的時候在i的子樹中已經走了j步而且不能再回到這個節點取到的最多的蘋果;f[i][j][1]就表示可以回來的。
那麼動規方程就是:
f[i][j][1]=max(f[i][j][1],f[i][j-t][1]+f[son][t-2][1])(表示走到子節點再走回來,在走向子節點喝回來的過程中需要走兩條邊,所以減去)
f[i][j][0]=max(f[i][j][0],f[i][j-t][1]+f[son][t-1][1])(表示從另外的位元組點走到根節點之後,走到son節點,不回來,由於只是下去沒有再回來,所以只是-1)
f[i][j][0]=max(f[i][j][0],f[i][j-t][1]+f[son][t-2][1])(表示從送節點回到根節點後,再從根節點向下走不回來的時候的最大值,因為這個時候跟第一種一樣來回總共走了兩次,所以-2)
這樣以後這個問題我們就可以解決了。

#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int N=110;const int K=210;vector <int> tr[N];int t,n,k,a[N],f[N][K][2];void dp(int x,int last){    int i,j,u,l;    for(i=0;i<tr[x].size();++i){        u=tr[x][i];        if(u==last) continue;        dp(tr[x][i],x);        for(j=k;j>=1;--j){            for(l=1;l<=j;++l){                f[x][j][1]=max(f[x][j][1],f[x][j-l][1]+f[u][l-2][1]);                f[x][j][0]=max(f[x][j][0],f[x][j-l][1]+f[u][l-1][0]);                f[x][j][0]=max(f[x][j][0],f[x][j-l][0]+f[u][l-2][1]);            }        }    }}int main(){    while(scanf("%d%d",&n,&k)==2){        int i,j,x,y;        for(i=1;i<N;++i) tr[i].clear();        memset(f,0,sizeof(f));        for(i=1;i<=n;++i){            scanf("%d",&a[i]);            for(j=0;j<=k;++j){                f[i][j][0]=f[i][j][1]=a[i];            }        }        for(i=1;i<n;++i){            scanf("%d%d",&x,&y);            tr[x].push_back(y);            tr[y].push_back(x);        }        dp(1,0);        printf("%d\n",max(f[1][k][0],f[1][k][1]));    }}

【poj2486】【Apple Tree】【樹形dp】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.