題目連接:https://codeforces.com/contest/1154/problem/Fc++
題解:spa
首先,能夠肯定的是:code
一、$(x,y)$ 裏 $x>k$ 的都不可能用;blog
二、確定買的是 $n$ 個鏟子裏,價格前 $k$ 小的鏟子。ci
而後,咱們用 $f[i]$ 表示買前 $i$ 個鏟子,最多能夠優惠掉多少錢。get
咱們假設 $g[x]$ 表明買 $x$ 個鏟子,最多能夠不用付 $g[x]$ 個鏟子的錢。獲得狀態轉移方程:it
$f[i] = \min_{j=0}^{i-1}(f[j]+\sum_{k=j+1}^{j+g[i-j]} a[k] )$class
換句話說,對於 $f[i]$,咱們遍歷全部的 $j \in [0,i)$:test
此時,咱們前 $j$ 個鏟子,最多優惠掉了 $f[j]$ 的錢,那麼 $(j+1) \sim i$ 這 $i-j$ 個鏟子,咱們直接用 $g[i-j]$ 的優惠,省掉這 $i-j$ 個鏟子裏最便宜的 $g[i-j]$ 個鏟子的錢。這樣,咱們就獲得了一種買前 $i$ 個鏟子的方案。(至於怎麼求 $f[i]$,即維護全部 $j$ 對應的方案中,省錢最多的那一個方案便可。)遍歷
那爲何不用 $g[i-j-1],g[i-j-2],\cdots$ 這些優惠呢?由於假設用這些優惠能省錢更多,那麼因爲 $f[i]$ 是遞增的,因此「$f[j+1]$ 加上用 $g[i-(j+1)]$ 的省錢量」,確定優於,「$f[j]$ 加上用 $g[i-j]$ 的省錢量」。而「$f[j+1]$ 加上用 $g[i-(j+1)]$ 的省錢量」會在下一個 $j$ 被算到,因此不影響正確性。
AC代碼:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; const int maxn=2e5+10; const int maxk=2e3+10; int n,m,k; int a[maxn],s[maxn]; int g[maxk]; int f[maxk]; int main() { cin>>n>>m>>k; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); if(x<=k) g[x]=max(g[x],y); } 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<=k;i++) { f[i]=0; for(int j=0;j<i;j++) f[i]=max(f[i],f[j]+s[j+g[i-j]]-s[j]); } cout<<s[k]-f[k]<<endl; }