P1510 精卫填海

1|0P1510 精卫填海

1|0最初思路

状态方程F[i]i是体积,F[i]指能填平该体积的最小体力。

推出转移方程F[i] = min(F[i], F[i-v[i]] + m[i])

但是代码实现只有10pts

#include <iostream> #include <cstdio> #include <cstring> using namespace std; int v, n, c; int k[10010], m[10010]; int F[100100]; int main() { cin >> v >> n >> c; for (int i = 1; i <= n; i++) { cin >> k[i] >> m[i]; } for (int i = 1; i <= v + 5000; i++) { F[i] = 0x3f3f3f; } for (int i = 1; i <= n; i++) { for (int j = v; j >= k[i]; j--) { F[j] = min(F[j], F[j - k[i]] + m[i]); } } if (c - F[v] >= 0) cout << c - F[v]; else cout << "Impossible"; return 0; }

1|0思路改进

如果是按照01背包,这层for循环枚举到k[i]是没问题的

for (int j = v; j >= k[i]; j--) { F[j] = min(F[j], F[j - k[i]] + m[i]); }

但是这是一个求最小值的问题,01背包不需要枚举j从零到k[i]的值是因为这些值本该为0,已经被提前初始化好了。

而求最小值的话,j从零到k[i]时要等于说要装填一个小于当前物品体积的东西,那只能取当前物品的体力值,毕竟没有比当前物品体积小的东西了,所以应加上j从零到k[i]的处理

for (int i = 1; i <= n; i++) { for (int j = v; j >= 0; j--) { if (j >= k[i]) F[j] = min(F[j], F[j - k[i]] + m[i]); else F[j] = min(F[j], m[i]); } }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17807142.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示