zoukankan      html  css  js  c++  java
  • Codeforces Round #552 (Div. 3) F. Shovels Shop (前缀和预处理+贪心+dp)

    题目:http://codeforces.com/contest/1154/problem/F

    题意:给你n个商品,然后还有m个特价活动,你买满x件就把你当前的x件中最便宜的y件价格免费,问你买k件花最少的钱是多少

    思路:首先这个特价活动就像点外卖一样满多少减多少,你可以分几次来使用同一个优惠或者不同的优惠,然后我们我们分析三个点

    1那个特价活动中x>k的我们肯定都不会使用,因为那个时候已经买满了k件

    2我们肯定是买最便宜的k件来使用特价活动

    3我们其实可以当成分开几组来使用优惠,就像外卖有些时候要分几次来点才划得来一样

    那么我们的思路就有了,我们dp[i]代表的是前i个物品的最高优惠价格,我们枚举最后一次使用特价活动是在哪个时候

    为了方便我们用几个数组分别记录一些东西

    s[i]    代表前i个的总花费

    g[i]   代表买满i个最多能减少多少个物品值   (因为活动可能有重复,买i个减x个和y个,这个时候要取最优的情况)

    dp[i] 代表的是前i个物品的最高优惠价格

    我们枚举最后一次使用活动要枚举边界在哪,所以我们要使用二重循环枚举

    这样转化一下,其实和我之前写的一篇数组分组是一样的思路了,主要还是要学会转化,建模

    #include<bits/stdc++.h>
    #define mod 1000007
    #define maxn 200001
    using namespace std;
    typedef long long ll;
    ll n,m,k;
    ll dp[maxn];
    ll s[maxn];
    ll g[maxn];
    ll a[maxn]; 
    int main(){
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+n+1);
        for(int i=1;i<=k;i++){
            s[i]=s[i-1]+a[i];//记录前缀和
        }
        for(int i=1;i<=m;i++){
            ll x,y;
            cin>>x>>y;
            if(x>k) continue;
            g[x]=max(g[x],y); //保留特价活动的最优减少数
        }
        for(int i=1;i<=k;i++){  //由前推后
            for(int j=0;j<i;j++){//枚举最后一次的特价活动位置
                dp[i]=max(dp[i],dp[j]+s[j+g[i-j]]-s[j]);
            }
        }
        cout<<s[k]-dp[k];
    } 
  • 相关阅读:
    python基础学习之路No.2 数据类型
    练习题 --- 猜数字游戏
    python基础学习之路No.1
    python+selenium第一步
    Self-introduction
    oracle中的number类型
    简单选项卡切换(二)
    简单选项卡切换(一)
    简单焦点轮播(二)(图片可滚动)
    简单焦点轮播(一)
  • 原文地址:https://www.cnblogs.com/Lis-/p/10724705.html
Copyright © 2011-2022 走看看