hdu 4044 树形DP

来源:互联网 发布:access创建表的sql语句 编辑:程序博客网 时间:2024/06/11 15:16

     这题写的我好纠结啊,过程中各种思路混乱,树P太弱了。。。dp[i][j]表示到i节点为根的子树有j元能得到的最小伤害的最大值,转移的话就是个一维背包,我是先做子树最后处理这个节点本身的权值的,需要注意price为0的节点,这地方坑了我两次,每个节点有多少钱的时候最多能得到多少伤害需要预处理出来。

#include<cstdio>#include<iostream>#include<cstring>#include<vector>#define N 1005using namespace std;vector<int>e[N];vector<pair<int,int> >p[N];int dp[N][205],kk[N],ok[N][205];int n,m;void dfs(int u,int fa){    int flag = 0;    for(int i = 0; i<e[u].size(); i++)    {        int v = e[u][i];        if(v == fa)continue;        dfs(v,u);        if(flag == 0)        {            for(int j = 0;j<=m;j++)                dp[u][j] = dp[v][j];            flag = 1;            continue;        }        for(int j = m; j>=0; j--)        {            dp[u][j] = min(dp[u][j],dp[v][0]);            for(int k = 1; k<=j; k++)                dp[u][j] = max(dp[u][j],min(dp[u][k],dp[v][j-k]));        }    }    for(int i = m;i>=0;i--)    {        int Max = 0;        for(int j = 0; j<=i; j++)            Max = max(dp[u][j]+ok[u][i-j],Max);        dp[u][i] = max(dp[u][i],Max);    }}int main(){    int t,i,j,k;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(i = 1; i<=n; i++)        {            e[i].clear();            p[i].clear();        }        for(i = 1; i<n; i++)        {            int u,v;            scanf("%d%d",&u,&v);            e[u].push_back(v);            e[v].push_back(u);        }        memset(ok,0,sizeof(ok));        scanf("%d",&m);        for(i = 1; i<=n; i++)        {            scanf("%d",&kk[i]);            for(j = 1; j<=kk[i]; j++)            {                int x,y;                scanf("%d%d",&x,&y);                for(k = 0;k<=m;k++)if(x<=k)ok[i][k] = max(ok[i][k],y);                p[i].push_back(make_pair(x,y));            }        }        memset(dp,0,sizeof(dp));        dfs(1,-1);        printf("%d\n",dp[1][m]);    }    return 0;}

原创粉丝点击