1. 程式人生 > >動態規劃 樹型DP

動態規劃 樹型DP

hide 初始化 turn max ble mes 測試 大數 ive

codves5565 二叉蘋果樹

時間限制: 1 s 空間限制: 128000 KB 題目描述 Description

有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)這棵樹共有N個結點(葉子點或者樹枝分叉點),編號為1-N,樹根編號一定是1。我們用一根樹枝兩端連接的結點的編號來描述一根樹枝的位置。現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。
給定需要保留的樹枝數量,求出最多能留住多少蘋果。

輸入描述 Input Description

第1行2個數,N和Q(1<=Q<= N,1<N<=100)。
N表示樹的結點數,Q表示要保留的樹枝數量。接下來N-1行描述樹枝的信息。
每行3個整數,前兩個是它連接的結點的編號。第3個數是這根樹枝上蘋果的數量。
每根樹枝上的蘋果不超過30000個。

輸出描述 Output Description

剩余蘋果的最大數量。

樣例輸入 Sample Input

5 2

1 3 1

1 4 10

2 3 20

3 5 20

樣例輸出 Sample Output

21

數據範圍及提示 Data Size & Hint

對於20%數據 n<=20;

對於100%數據1<N<=100,1<=Q<= N.

技術分享
#include<cstdio>
#include<algorithm>
#include<cstring>
using
namespace std; struct node { int l,r,c; }map[2001]; int f[1005][1005]; int n,q,maxx=0; void dfs(int i,int j) { int k; if(j==0) f[i][j]=0; else if(map[i].r==0&&map[i].l==0) f[i][j]=map[i].c; else { f[i][j]=0; for(k=0;k<j;k++) { if(f[map[i].l][k]==0
) dfs(map[i].l,k); if(f[map[i].r][j-k-1]==0) dfs(map[i].r,j-k-1); f[i][j]=max(f[i][j],f[map[i].l][k]+f[map[i].r][j-k-1]+map[i].c); // maxx=max(maxx,f[i][j]); //printf("%d ",maxx); } } } int main() { scanf("%d %d",&n,&q); int v,u,c; for(int i=1;i<n;i++) { int p=0; scanf("%d %d %d",&v,&u,&c); for(int j=1;j<=n;j++) if(map[j].l==u||map[j].r==u) p=1; if(p==0) { if(map[v].l==0) map[v].l=u; else if(map[v].r==0) map[v].r=u; map[u].c=c; } else { if(map[u].l==0) map[u].l=v; else if(map[u].r==0) map[u].r=v; map[v].c=c; } } //for(int i=1;i<=n;i++) printf("%d %d %d\n",map[i].l,map[i].r,map[i].c); dfs(1,q+1); //for(int i=1;i<=n;i++) printf("%d ",map[i]); printf("%d",f[1][q+1]); }
View Code

技術分享

初始化:f[i][0]=0,f[i][1]=map[i];

轉移方程:f[i][j]=max(f[i][j],f[map[i].l][k]+f[map[i].r][j-k-1]+map[i].c);

謝謝姚老教導;

接下來膜ccz大爺 附代碼 很強勢;

技術分享
#include<bits/stdc++.h>
struct edge{
    int to,v;
};
int n,q;
std::vector<edge>e[107];
int f[107][107],sz[107],v[107];
void maxs(int&a,int b){if(a<b)a=b;}
void f1(int w,int pa){
    sz[w]=1;
    f[w][1]=v[w];
    for(int i=0;i<e[w].size();++i){
        int u=e[w][i].to;
        if(u==pa)continue;
        v[u]=e[w][i].v;
        f1(u,w);
        for(int k=sz[w];k>=1;--k)
        for(int j=1;j<=sz[u];++j){
            maxs(f[w][k+j],f[w][k]+f[u][j]);
        }
        sz[w]+=sz[u];
    }
}
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1,a,b,c;i<n;++i){
        scanf("%d%d%d",&a,&b,&c);
        e[a].push_back((edge){b,c});
        e[b].push_back((edge){a,c});
    }
    f1(1,0);
    printf("%d\n",f[1][q+1]);
    return 0;
}
View Code

------------------------

codves1380 沒有上司的舞會

時間限制: 1 s 空間限制: 128000 KB 題目描述 Description

Ural大學有N個職員,編號為1~N。他們有從屬關系,也就是說他們的關系就像一棵以校長為根的樹,父結點就是子結點的直接上司。每個職員有一個快樂指數。現在有個周年慶宴會,要求與會職員的快樂指數最大。但是,沒有職員願和直接上司一起與會。

輸入描述 Input Description

第一行一個整數N。(1<=N<=6000)
接下來N行,第i+1行表示i號職員的快樂指數Ri。(-128<=Ri<=127)
接下來N-1行,每行輸入一對整數L,K。表示K是L的直接上司。
最後一行輸入0,0。

輸出描述 Output Description

輸出最大的快樂指數。

樣例輸入 Sample Input

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

樣例輸出 Sample Output

5

數據範圍及提示 Data Size & Hint

各個測試點1s

技術分享
#include<cstdio>
#include<algorithm>
#include<cstring>
#define long long ll
using namespace std;
const int N=6010;
int map[N];
struct node
{
    int to,next;
}e[N*2];
int boss[N]={0};
int first[N],cnt=0;
int is_boss;
int f[N][5];

void insert(int v,int u)
{
     e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;
     //printf("===========\n%d %d %d\n==========\n",e[cnt].to,e[cnt].next,first[cnt]);
}

void dfs(int x)
{
        f[x][0]=0;f[x][1]=map[x];
        for(int i=first[x];i;i=e[i].next)
        {
            int p=e[i].to;
            dfs(p);
            f[x][0]+=max(f[p][0],f[p][1]);
            f[x][1]+=f[p][0];
            //printf("%d %d\n",f[x][0],f[x][1]);
        }
}    

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&map[i]);
    int v,u;
    while(1)
    {
        scanf("%d %d",&v,&u);
        if(v+u==0) break;
        boss[v]++;
        insert(u,v);
    }
    //printf("-------------------------\n");
    for(int i=1;i<=n;i++) if(!boss[i]) {is_boss=i;break;}
    //printf("%d \n",is_boss);
    dfs(is_boss);
    printf("%d",max(f[is_boss][1],f[is_boss][0]));            
    return 0;
}
View Code

轉移方程:

技術分享

f[]中的0代表不選,1代表選;

謝謝姚老教導(again);

-----------------------------------------

動態規劃 樹型DP