[背包]CF19B Checkout Assistant 题解
背包好题,也包含了一种思想。
题意
有若干物品,每个物品有两个属性 , ,表示这个物品的费用 以及如果选择了这个物品我可以白嫖 个物品。最小的费用数。
主要思想
如果我们正向考虑,似乎十分难想到一个贪心策略。就算我现在知道了我们现在有选择 个物品的机会,我们也不知道选择给谁这个机会,所以说我们似乎不能从正面开始考虑。
正确的思路是将选择 个物品的机会想成是一个容量为 的物品,为什么?因为我们可以想到,如果我们有选择 个物品的机会,我们可以记在那里,不去想选哪 个物品最好,而是看看我选完这 个物品之后选什么。那么如果我把它想成一个 的物品,我只要到容量大于等于 就行了。
这样的话我们的话就可以转成一个 01 背包的问题了。记得要开 long long 。
并且学到了一个新的东西, memset 对于 long long 的数组初始化也会初始化到 long long 可以承受的最大值的。
代码
#include <bits/stdc++.h>
#define debug puts("I love Newhanser forever!!!!!");
#define pb push_back
using namespace std;
template <typename T>inline void read(T& t){
t=0; register char ch=getchar(); register int fflag=1;
while(!('0'<=ch&&ch<='9')){if(ch=='-') fflag=-1;ch=getchar();}
while(('0'<=ch&&ch<='9')){t=t*10+ch-'0'; ch=getchar();} t*=fflag;
}
const int MAXN=5086;
typedef long long ll;
int n,V,v[MAXN];
ll dp[MAXN],c[MAXN];
int main(){
read(n);
for(int i=1;i<=n;++i){
read(v[i]);
v[i]++;
read(c[i]);
V=max(v[i],V);
}
V+=n;
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
for(int i=1;i<=n;++i)
for(int j=V;j>=v[i];--j)
dp[j]=min(dp[j-v[i]]+c[i],dp[j]);
ll ans=2e12;
for(int j=n;j<=V;++j) ans=min(ans,dp[j]);
cout<<ans<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通