hdu 4003 Find Metal Mineral (树形dp+分组背包)

版权声明:本文为博主原创文章,转载请说明出处。 https://blog.csdn.net/xianpingping/article/details/81981215

这道题有两种做法,但是都是树形dp+分组背包

思路1:逆向考虑。

参考:https://blog.csdn.net/shuangde800/article/details/10217167

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
int sum,cnt;
int dp[maxn][20],head[maxn];
int n,m,k;
struct node{
    int to,next,val;
}G[maxn*2];
void add(int u,int v,int val)
{
    G[++cnt].to=v;
    G[cnt].val=val;
    G[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa){
    for(int i=head[u];i!=-1;i=G[i].next){
        int son=G[i].to;
        int val=G[i].val;
        if(son==fa)
            continue;
        dfs(son,u);
        for(int j=k;j>=1;j--){
            for(int l=1;l<=j;l++){
                dp[u][j]=max(dp[u][j],dp[u][j-l]+dp[son][l]+2*val-l*val);
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k)){
        memset(head,-1,sizeof(head));
        memset(dp,0,sizeof(dp));
        cnt=0;
        sum=0;
        for(int i=1;i<n;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            sum+=z;
            add(x,y,z);
            add(y,x,z);
        }
        dfs(m,-1);
        printf("%d\n",sum*2-dp[m][k]);
    }
    return 0;
}

思路2:正向考虑:

参考:

https://blog.csdn.net/yexiaohhjk/article/details/52862116

#include<bits/stdc++.h>
using namespace std;
const int maxn=20005;
struct node{
    int v,next,val;
}G[maxn];
int head[maxn],dp[maxn][20];
int n,s,k,cnt;
void add(int u,int v,int val){
    G[++cnt].v=v;
    G[cnt].val=val;
    G[cnt].next=head[u];
    head[u]=cnt;
    ///cnt++;
}
void dfs(int root,int p){
    int i,j,l,son;
    for(i=head[root];i!=-1;i=G[i].next){
        son=G[i].v;
        if(son==p)
            continue;
        dfs(son,root);
        for(j=k;j>=0;j--){
            dp[root][j]+=dp[son][0]+2*G[i].val;///先将dp[son][0]放进背包,由于dp[son][0]是表示用一个机器人去走完所有子树最后又回pos来,所以花费要乘2
            for(l=1;l<=j;l++){///分组背包
                dp[root][j]=min(dp[root][j],dp[root][j-l]+dp[son][l]+l*G[i].val);
            }
        }
    }
}
int main()
{
    int x,y,w;
    while(~scanf("%d%d%d",&n,&s,&k)){
        cnt=0;
        memset(head,-1,sizeof(head));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
            add(y,x,w);
        }
        dfs(s,-1);
        printf("%d\n",dp[s][k]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xianpingping/article/details/81981215