CF #552(div3)F 背包问题

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

题意:一个商店有n个物品,每个物品只能买一次,同时有m种优惠,即一次买够x件后,这x件中最便宜的k件将免费

一个要买k个物品,求最小花费。

分析:如果没有优惠的话,就是一种很普通的背包问题,其状态转移方程就为f[i]=min(f[j],f[j]+剩下的i-j件物品的价格)

加上优惠券后只需要多一个g[x]数组来存储最佳优惠价格就好,具体请看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;//这个数是1e9数量级的,且可以用memset函数 
const int maxn=2e5+7;
const double pi=acos(-1);
const int mod=1e9+7;
int a[maxn],g[maxn],f[maxn];
int main(){
    int n,m,k;scanf("%d%d%d",&n,&m,&k);
    memset(f,inf,sizeof(f));
    //fill(f,f+maxn,inf);
    f[0]=0;//千万别忘了这个初始化 
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)a[i]=a[i-1]+a[i]; 
    for(int i=1;i<=m;i++){
        int x,y;scanf("%d%d",&x,&y);
        g[x]=max(g[x],y);//买x个货物最多可以免费多少个 
    }
    //dp开始
    for(int i=1;i<=k;i++){
        //f[i]=inf;
        for(int j=0;j<i;j++){
            f[i]=min(f[i],f[j]+a[i]-a[j+g[i-j]]);
        }
    }
    cout<<f[k]<<endl; 
    return 0;
}

 

posted @ 2019-04-22 18:50  清酒令  阅读(254)  评论(0编辑  收藏  举报