01 背包的变形
消失之物
链接:https://www.luogu.com.cn/problem/P4141
题目描述
ftiasch 有
“要使用剩下的
她把答案记为
输入格式
第一行两个整数
第二行
输出格式
输出一个
样例 #1
样例输入 #1
3 2
1 1 2
样例输出 #1
11
11
21
提示
【数据范围】
对于
【样例解释】
如果物品 3 丢失的话,只有一种方法装满容量是 2 的背包,即选择物品 1 和物品 2。
解答
f[j][0]
:表示未删物品前的,组成体积为j
的方案数f[j][1]
:表示删除某个物品,组成体积为j
的方案数- 前者就是一个
01
背包问题 - 后者状态转移主要是
f[j][1] = f[j][0] - f[j - v[i]][1]
- 解释:因为
f[j][0]
表示未删,多了部分,需要删除一些,所以枚举每个物品,表示可能删除的,假设当前物品为i
,f[j - v[i]][1]
表示的是组成体积j - v[i]
且前面已经删除一个数了 - 而这个体积只要加上
v[i]
,也就是选这个i
物品,便可组成体积j
,我们枚举的也就是删除i
物品的方案,所以需要删除这一部分 - 下述
%10
的原因是题目要求输出末尾数字即可
#include <iostream>
#include <cstring>
using namespace std;
const int N = 2010;
int v[N];
int f[N][2];
int n, m;
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i];
f[0][0] = f[0][1] = 1;
for(int i = 1; i <= n; i++)
for (int j = m; j >= v[i]; j--)
{
f[j][0] += f[j - v[i]][0];
f[j][0] %= 10;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (j >= v[i]) f[j][1] = (f[j][0] - f[j - v[i]][1] + 10) % 10;
else f[j][1] = f[j][0];
cout << f[j][1];
}
cout << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」