https://codeforces.com/contest/1154/problem/F
给定m个折扣
每个折扣的{x,y}的意思是每次购买如果买到确切的x只铲子就其中的最便宜的y只铲子免付;
先贪心一波,因为要买k只,而不管折扣怎么变,怎么买,我们都要买原价最便宜的k只铲子,这贪心是对的
接着就选择折扣offers ,明显要dp解决,贪心贪不出(复杂度太高);
设dp【i】表示买i只铲子的最小花费;
所以转移方程:dp【i】=min(f【i】,(选择折扣的处理));
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll inf=1e15; const int M=2e5+5; ll a[M],b[M],dp[M],sum[M]; inline int read(){ ll sum=0; int x=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') x=0; ch=getchar(); } while(ch>='0'&&ch<='9') sum=(sum<<1)+(sum<<3)+(ch^48),ch=getchar(); return x?sum:-sum; } int main(){ ios::sync_with_stdio(false); ll n,m,k; n=read(); m=read(); k=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=m;i++){ ll x,y; x=read(); y=read(); if(x<=k) b[x]=max(b[x],y); } sort(a+1,a+1+n); for(int i=1;i<=k;i++) sum[i]=sum[i-1]+a[i]; for(int i=1;i<=k;i++) dp[i]=inf; dp[0]=0; for(int i=1;i<=k;i++) for(int j=0;j<i;j++) dp[i]=min(dp[i],dp[j]+sum[i]-sum[j+b[i-j]]); cout<<dp[k]; return 0; }