zoukankan      html  css  js  c++  java
  • codeforces 816 E. Karen and Supermarket(树形dp)

    题目链接:http://codeforces.com/contest/816/problem/E

    题意:有n件商品,每件有价格ci,优惠券di,对于i>=2,使用di的条件为:xi的优惠券需要被使用,问初始金钱为b时 最多能买多少件商品? n<=5000,ci,di,b<=1e9

    题解:显然是一道树形dp由于有两种情况就是当前点为根结点的时候选择打折还是不打折,如果选不打折之后的节点都不能打折。

    不妨设dp[i][j][flag]表示i为根j为种类数,flag为状态表示选不选打折的最小花费。转移方程为

     dp[u][j + l][0] = min(dp[u][j + l][0] , dp[u][j][0] + dp[v][l][0]);

     dp[u][j + l][1] = min(dp[u][j + l][1] , min(dp[u][j][1] + dp[v][l][0] , dp[u][j][1] + dp[v][l][1]));

    具体看代码。

    #include <iostream>
    #include <cstring>
    #include <vector>
    #define inf 0X3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int M = 5e3 + 10;
    vector<int>vc[M];
    ll pa[M] , pb[M] , dp[M][M][2] , sz[M];
    void dfs(int u) {
        int len = vc[u].size();
        sz[u] = 1;
        dp[u][0][0] = 0 , dp[u][1][0] = pa[u] , dp[u][1][1] = pa[u] - pb[u];
        for(int i = 0 ; i < len ; i++) {
            int v = vc[u][i];
            dfs(v);
            for(ll j = sz[u] ; j >= 0 ; j--) {
                for(ll l = 0 ; l <= sz[v] ; l++) {
                    dp[u][j + l][0] = min(dp[u][j + l][0] , dp[u][j][0] + dp[v][l][0]);
                    dp[u][j + l][1] = min(dp[u][j + l][1] , min(dp[u][j][1] + dp[v][l][0] , dp[u][j][1] + dp[v][l][1]));
                }
            }
            sz[u] += sz[v];
        }//这里看似是3个for实际上就是3个for但是复杂度却不是O(n^3),由于sz[i]表示的是以i为根的最多有几个子节点类似前缀的一种东西,由于dfs,这些sz只会用一次不会有重复。所以理论上复杂度就是O(n^2)。
    }
    int main() {
        int n , b;
        scanf("%d%d" , &n , &b);
        for(int i = 1 ; i <= n ; i++) {
            int c , d , x;
            if(i == 1) {
                scanf("%d%d" , &c , &d);
                pa[i] = c , pb[i] = d;
            }
            else {
                scanf("%d%d%d" , &c , &d , &x);
                pa[i] = c , pb[i] = d;
                vc[x].push_back(i);
            }
        }
        memset(dp , inf , sizeof(dp));
        dfs(1);
        int ans = 0;
        for(int i = 0 ; i <= n ; i++) {
            if(dp[1][i][0] <= b || dp[1][i][1] <= b) ans = i;
        }
        printf("%d
    " , ans);
        return 0;
    }
    
  • 相关阅读:
    ui自动化---select标签和浏览器等待
    ui自动化--鼠标操作ActionChains
    ui自动化---WebDriverApi接口
    ui自动化---CssSelector
    ui自动化--xpath
    html基础:jquery的ajax获取form表单数据
    grep使用方法
    VI打开和编辑多个文件的命令 分屏操作
    C语言编译器 cc 编译原理
    zabbix的mysql优化后的配置文件
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7056547.html
Copyright © 2011-2022 走看看