CF19B Checkout Assistant
题目大意:Bob在超市买 (偷) 付款时有n件物品。每件商品的价值 c[i] 元,要花 t[i] 秒扫描。当收银员扫描某件商品时,Bob偷一些其他商品会打掩护,偷一件商品要一秒钟 (空间魔法) 。求Bob 至少要付给收银员的钱。 (收银员扫描商品的顺序由收银员按顺序扫描 Bob 决定)
算法思路:DP,01背包变形
想法: 1.首先,有一个贪婪的想法,那就是收银员扫描商品时偷走 t[i] 件商品 (火力全开)。 可以用从 c[i] 的代价获得 t[i] 1 一个物体。然后你可以用01背包来寻求最好的想法。
2.因为有些商品扫描时间可能太长,扫描前所有的物品都被偷了 (计算失败的小偷) 。 会有时间溢出,但总扫描时间可以控制在最大溢出时 n max (t[1],t[2],t[3] … t[n]) 之内。
3.最终选择答案时,应在法律范围内取最小值。(包括时间溢出)
4.初始化时应去除 f[0] 以外的 f[i] 初始化为正无穷。
#include<bits/stdc .h> using namespace std; typedef long long ll; const int N=2010; int n,v; int t[N],c[N]; ll f[2*N]; int main(){
scanf("%d",&n); for(int i=1;i<=n;i ){
scanf("%d%d",&t[i],&c[i]); t[i] ;v=max(v,t[i]); } v =n; ///计算时间溢出的最大值 memset(f,0x3f,sizeof(f)); f[0]=0;
for(int i=1;i<=n;i++){
for(int j=v;j>=t[i];j--){
f[j]=min(f[j],f[j-t[i]]+c[i]);
}
}
ll ans=2e12;
for(int i=n;i<=v;i++) ans=min(ans,f[i]);
printf("%lld",ans);
return 0;
}
(蒟蒻多次提交未果后) 学习了洛谷Silence_water的题解。
PS:作为一名蒟蒻,对于八方神犇的合理建议都是感激不尽的儿~~