csu 2014 summer training day 4 樹形dp升階

POJ 1155ios

題意:電視臺發送信號給不少用戶,每一個用戶有願意出的錢,電視臺通過的路線都有必定費用,求電視臺不損失的狀況下最多給多少用戶發送信號。app

要知道用戶都在葉子節點,費用消耗在使用選擇的路徑上,每條路徑的使用費用給出,每一個用戶支付的費用給出。ide

輸入:N爲總節點數,M爲用戶數,1爲電視臺, 2 to N-M 是中轉站,N-M+1到N是潛在用戶spa

對於1到N-M的中繼點,給出鏈接的點的個數K,K對(A,C)表示鏈接到A點,這條路徑的費用是C3d

最後是M個整數,表示用戶支付的費用code

分析:blog

int num[maxn];//記錄每一個節點下面的總用戶數 int dp[maxn][maxn];//i:i的子樹中,j:節點下面的使用用戶數,能達到的最大的剩餘利潤 //dp:最大剩餘利潤:線路費用-使用用戶支付的費用
至關於樹形揹包:
dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
temp[j]表示原來的dp[u][j]
對於搜索出來的一棵樹,對於它的孩子,能夠選擇加仍是不加,其中len[u][i]剛好表示u到當前選擇的v的代價

完整寫法:
 for(int j=0;j<=num[u];j++){ temp[j]=dp[u][j]; } for(int j=0;j<=num[u];j++){ for(int k=1;k<=num[v];k++){//注意k!=0,不然多減小了i dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]); } } num[u]+=num[v];

代碼:get

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <vector>
 5 #define maxn 3100
 6 #define INF 99999999
 7 using namespace std;
 8 
 9 int num[maxn];//記錄每一個節點下面的總用戶數
10 int dp[maxn][maxn];//i:處理的節點數,j:節點下面的使用用戶數
11 //dp:最大剩餘利潤:線路費用-使用用戶支付的費用
12 int N,M;
13 vector<int>G[maxn];
14 vector<int>len[maxn];
15 int temp[maxn];
16 void dfs(int u,int fa){
17 
18 //    cout<<"u="<<u<<endl;
19 //    for(int i=0;i<G[u].size();i++){
20 //        int v=G[u][i];
21 //        if (v==fa) continue;
22 //        dfs(v);
23 //        num[u]+=num[v];
24 //    }
25 //    //用子節點更新u
26 //    int sum=0;
27 //    for(int i=0;i<G[u].size();i++){//依次枚舉下層節點
28 //        int v=G[u][i];
29 //        if (v==fa) continue;
30 //        for(int j=0;j<=sum;j++){//設置這個的緣由是,仔細看下面,本來的dp[u][j]已經被覆蓋了
31 //            temp[j]=dp[u][j];
32 //        }
33 //        for(int j=0;j<=sum;j++){
34 //            for(int k=0;k<=num[v];k++){
35 //                dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
36 //            }
37 //        }
38 //        sum+=num[v];
39 //    }
40 //咱們能夠看出,上面兩部分能夠和在一塊兒寫,並且每次更新的num[u]就是sum
41 
42     dp[u][0]=0;
43     for(int i=0;i<G[u].size();i++){
44         int v=G[u][i];
45         if (v==fa) continue;
46         dfs(v,u);
47         for(int j=0;j<=num[u];j++){
48             temp[j]=dp[u][j];
49         }
50         for(int j=0;j<=num[u];j++){
51             for(int k=1;k<=num[v];k++){//注意k!=0,不然多減小了i
52                 dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
53             }
54         }
55         num[u]+=num[v];
56     }
57     return ;
58 }
59 void solve(){
60     for(int i=M;i>=0;i--){
61         if (dp[1][i]>=0) {
62             printf("%d\n",i);
63             break;
64         }
65     }
66     return ;
67 }
68 int main(){
69     while(~scanf("%d%d",&N,&M)){
70         for(int i=0;i<=N;i++) G[i].clear();
71         for(int i=1;i<=N-M;i++){
72             int k;
73             scanf("%d",&k);
74             for(int j=1;j<=k;j++){
75                 int v,c;
76                 scanf("%d%d",&v,&c);
77                 G[i].push_back(v);
78                 len[i].push_back(c);
79             }
80         }
81         memset(num,0,sizeof(num));
82         for(int i=0;i<=N;i++){
83             for(int j=0;j<=N;j++) dp[i][j]=-INF;
84         }
85         for(int i=N-M+1;i<=N;i++){
86             scanf("%d",&dp[i][1]);
87             num[i]=1;
88         }
89         dfs(1,-1);
90         solve();
91     }
92     return 0;
93 }
View Code

 

POJ 2486string

題意:Wshxzt從根節點1開始在蘋果樹上游歷,樹上的每一個節點都會存在apple[i]個蘋果,從一個節點到它的鄰節點耗費步數1。如今Wshxzt能夠步行step步,求她能夠獲得的最大蘋果數量。it

輸入:N節點數,K最大步數,每一個節點的蘋果數,N-1條邊

分析:

代碼:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<vector>
 5 #define MAXN 110
 6 #define MAXK 220
 7 using namespace std;
 8 
 9 vector<int>G[MAXN];
10 int anum[MAXN];
11 int dp[MAXN][MAXK][2];
12 int N,K;
13 int temp[MAXN];
14 void dfs(int u,int fa){
15     dp[u][0][1]=anum[u];
16     dp[u][0][0]=anum[u];
17     for(int i=0;i<G[u].size();i++){
18         int v=G[u][i];
19         if (v==fa) {
20             continue;
21         }
22         dfs(v,u);
23         for(int j=K;j>=0;j--){
24             for(int t=1;t<=j;t++){
25                 dp[u][j][0]=max(dp[u][j][0],dp[v][t-1][0]+dp[u][j-t][1]);
26                 if (t==1) continue;
27                 dp[u][j][0]=max(dp[u][j][0],dp[v][t-2][1]+dp[u][j-t][0]);
28                 dp[u][j][1]=max(dp[u][j][1],dp[v][t-2][1]+dp[u][j-t][1]);
29             }
30         }
31     }
32 
33     return ;
34 }
35 int main(){
36     while(~scanf("%d%d",&N,&K)){
37         for(int i=1;i<=N;i++){
38             scanf("%d",&anum[i]);
39         }
40         for(int i=0;i<=N;i++) G[i].clear();
41         for(int i=1;i<=N-1;i++){
42             int u,v;
43             scanf("%d%d",&u,&v);
44             G[u].push_back(v);
45             G[v].push_back(u);
46         }
47         memset(dp,0,sizeof(dp));
48         for(int i=0;i<=N;i++){
49             for(int j=0;j<=K;j++) dp[i][j][0]=dp[i][j][1]=anum[i];
50         }
51         dfs(1,-1);
52         printf("%d\n",dp[1][K][0]);
53     }
54     return 0;
55 }
View Code

 

POJ 1947

 

 

POJ 1848

 

 

 

POJ 1655

相關文章
相關標籤/搜索