zoukankan      html  css  js  c++  java
  • CodeForces 816E Karen and Supermarket ——(树形DP)

      题意:有n件商品,每件商品都最多只能被买一次,且有一个原价和一个如果使用优惠券以后可以减少的价格,同时,除了第一件商品以外每件商品都有一个xi属性,表示买这个商品时如果要使用优惠券必须已经使用了xi的优惠券。现在有B的钱,问在不超过B的钱的情况下最多能买多少件商品。

      做法:因为根据x属性,所有商品能够被连缀成一棵以1为根节点的树,因此考虑树形dp,因为n=5000,所以定义状态如下:dp[i][j][p],表示从i这件开始买,已经买了j件商品且i这件商品是否已经使用了优惠券(1表示使用,0表示没有)的最小花费。要注意的是,由于每件商品最多只能被购买一次,因此在dfs里面枚举i和j的时候需要从大到小(和01背包一个道理)。代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N = 5000 + 5;
     5 const int mod = 1e9 + 7;
     6 typedef pair<int,int> pii;
     7 
     8 int n, money;
     9 vector<int> G[N];
    10 int a[N], b[N];
    11 ll dp[N][N][2]; // from i, buy j already, 0 -> not use quan
    12 int sz[N];
    13 void update(ll &x, ll y) {if(x > y) x = y;}
    14 void dfs(int u)
    15 {
    16     dp[u][0][0] = 0;
    17     dp[u][1][0] = a[u];
    18     dp[u][1][1] = a[u] - b[u];
    19     sz[u] = 1;
    20     for(int v: G[u])
    21     {
    22         dfs(v);
    23         for(int i=sz[u];i>=0;i--)
    24         {
    25             for(int j=sz[v];j>=0;j--)
    26             {
    27                 update(dp[u][i+j][0], dp[v][j][0] + dp[u][i][0]);
    28                 update(dp[u][i+j][1], min(dp[v][j][0], dp[v][j][1]) + dp[u][i][1]);
    29             }
    30         }
    31         sz[u] += sz[v];
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     cin >> n >> money;
    38     for(int v=1;v<=n;v++)
    39     {
    40         scanf("%d%d",a+v,b+v);
    41         if(v > 1)
    42         {
    43             int u; scanf("%d",&u);
    44             G[u].push_back(v);
    45         }
    46     }
    47     memset(dp,0x3f,sizeof dp);
    48     dfs(1);
    49     for(int i=n;i>=0;i--)
    50     {
    51         if(dp[1][i][0] <= money || dp[1][i][1] <= money)
    52         {
    53             printf("%d
    ",i);
    54             break;
    55         }
    56     }
    57     return 0;
    58 }

     

  • 相关阅读:
    675 对象的引用-浅拷贝-深拷贝
    674 vue3侦听器watch
    673 vue计算属性:缓存,setter和getter
    明明有了promise,为啥还需要async await?
    Js常用数组方法汇总
    一些非常有用的Js单行代码
    Js获取验证码倒计时
    前端截取字符串:JS截取字符串之substring、substr和slice详解
    javascript全局变量与局部变量
    JS实现快速排序算法
  • 原文地址:https://www.cnblogs.com/zzyDS/p/7114953.html
Copyright © 2011-2022 走看看