hdu 3593

来源:互联网 发布:福建广电网络人工电话 编辑:程序博客网 时间:2024/04/19 00:57

终于理解树形依赖背包啦~


这个树形DP的转移方程还是比较简单的。

树形依赖背包的优化:

设当前结点为 x,因为选取物品 x 需要强制选取物品 fa(x)

所以直接令 dp(x)=dp(fa(x)) 并限制背包空间,然后处理 dp(son(x))

最后强制加入物品 x,即用 dp(x)+g(x)来更新 dp(fa(x)) 即可。

这样就在强制选取物品 fa(x) 的前提下,选择了物品 x

与原问题相比,优化了泛化物品的合并,时间复杂度降到 O(G)

时间复杂度:O(NG)


另外这题数据有点小问题,读入部分要改成奇怪的方式才能过。。。QwQ

void init(){    for(int i = 1, father; i <= N; i++)    {//      read(cost[i]), read(att[i]), read(fa[i]);        scanf("%d%d%d", &cost[i], &att[i], &father);        if(father == i) father = 0;        NewEdge(father, i);    }}

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <vector>#include <utility>#include <stack>#include <queue>#include <iostream>#include <algorithm>template<class Num>void read(Num &x){    char c; int flag = 1;    while((c = getchar()) < '0' || c > '9')        if(c == '-') flag *= -1;    x = c - '0';    while((c = getchar()) >= '0' && c <= '9')        x = (x<<3) + (x<<1) + (c-'0');    x *= flag;    return;}template<class Num>void write(Num x){    if(x < 0) putchar('-'), x = -x;    static char s[20];int sl = 0;    while(x) s[sl++] = x%10 + '0',x /= 10;    if(!sl) {putchar('0');return;}    while(sl) putchar(s[--sl]);}const int maxn = 1e5+50, maxG = 10005, rem = 505;int N, G, dp[rem][maxG];int cost[maxn], att[maxn], fa[maxn];struct Edge{    int v, next;    Edge(int v = 0,int next = 0):v(v),next(next){}}edge[maxn];int head[maxn], el = 0;void NewEdge(int u,int v){    edge[++el] = Edge(v, head[u]), head[u] = el;}void dfs(int a,int size){    for(int i = head[a]; i; i = edge[i].next)    {        int p = edge[i].v;        if(!head[p])        {            for(int j = size; j >= cost[p]; j--)                dp[a][j] = std::max(dp[a][j], dp[a][j - cost[p]] + att[p]);        }        else        {            if(size >= cost[p])              {                  for(int j = 0; j <= size - cost[p]; j++) dp[p][j] = dp[a][j];                  dfs(p, size - cost[p]);                  for(int j = size; j >= cost[p]; j--)                    dp[a][j] = std::max(dp[a][j], dp[p][j - cost[p]] + att[p]);              }          }    }}void clear(){    el = 0, cost[0] = att[0] = 0;    memset(head, 0, sizeof(head));    memset(dp, 0, sizeof(dp));      }void init(){    for(int i = 1; i <= N; i++)    {        read(cost[i]), read(att[i]), read(fa[i]);        if(fa[i] == i) fa[i] = 0;        NewEdge(fa[i], i);    }}int main(){#ifndef ONLINE_JUDGE    freopen("3593.in","r",stdin);    freopen("3593.out","w",stdout);#endif    while(scanf("%d%d",&N,&G) != EOF)    {        clear(), init();        dfs(0, G);        write(dp[0][G]), puts("");        }#ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif    return 0;}

0 0