题目链接:
http://codeforces.com/contest/1154/problem/F
题意:
有$n$个物品,$m$条优惠
每个优惠的格式是,买$x_i$个物品,最便宜的$y_i$个物品免费
每条优惠可以无限次使用(当时以为每个优惠只能用一次)
可以买一个物品,不参与优惠
求买k个物品的最低花费
数据范围:
$1 le n, m le 2 cdot 10^5, 1 le k le min(n, 2000)$
$1 le a_i le 2 cdot 10^5$
$1 le y_i le x_i le n$
分析:
太蠢了,一开始以为每条优惠只能用一次,并且以为,优惠都有一个使用次序,所以先给优惠排序,然后枚举优惠更新dp数组
原来每个优惠能用无限次,那么我们再加入一条$(1,0)$优惠,枚举购买长度,用每个优惠对它更新
虽然两种方法的状态定义得相同。。。。
ac代码:
#include<bits/stdc++.h> #define ll long long #define pa pair<int,int> #define mak make_pair using namespace std; const int maxn=2e5+3000; const ll INF=1e18; int price[maxn],x[maxn],y[maxn]; ll sum[maxn],dp[2005]; int main() { int n,m,k; scanf("%d %d %d",&n,&m,&k); for(int i=1; i<=n; i++)scanf("%d",&price[i]); sort(price+1,price+1+n); for(int i=1;i<=k;i++)sum[i]=sum[i-1]+price[i]; for(int i=1; i<=m; i++) scanf("%d %d",&x[i],&y[i]); x[m+1]=1;y[m+1]=0; for(int i=0; i<=k; i++)dp[i]=INF; dp[0]=0; for(int i=1;i<=k;i++) { for(int j=1;j<=m+1;j++) if(i-x[j]>=0) dp[i]=min(dp[i],dp[i-x[j]]+sum[i]-sum[i-x[j]+y[j]]); } printf("%lld ",dp[k]); return 0; }