NC210520 Min酱要旅行

题目链接

题目

题目描述

从前有个富帅叫做Min酱,他很喜欢出门旅行,每次出门旅行,他会准备很大一个包裹以及一大堆东西,然后尝试各种方案去塞满它。
然而每次出门前,Min酱都会有个小小的烦恼。众所周知,富帅是很讨妹子喜欢的,所以Min酱也是有大把大把的妹子,每次出门都会有一只妹子随行。然而这些妹子总是会非常排斥Min酱准备的众多东西中的一件(也许是因为这件东西是其它妹子送给Min酱的),这件东西Min酱是万万不敢带上的,否则的话……嘿嘿嘿。另外,妹子们嫌Min酱的包裹太丑了,会自带一个包裹去换掉Min酱的包裹。
Min酱是个控制欲很强的人,然而这样一来,Min酱就不知道可以用多少种方案去填充包裹了,所以Min酱很郁闷。
于是Min酱找到了聪明的你,希望你能帮助他解决这些问题。
另外,Min酱是个典型的懒人,他不希望每次带不同的妹子出去都麻烦你,所以他希望你能给出有 K1..Kn 件物品,第 i 件不能带并且包裹大小为 1..M 的所有方案数。

输入描述

可能有多组数据。对于每一组数据:
第一行,两个整数 n,m ,分别表示物品数量和妹子带的包裹的最大容积。
第二行,n 个正整数,分别表示物品 Ki 的体积。

输出描述

对于每一组数据,输出一个 n×m 的矩阵,第 ij 列表示包裹容积为 j ,不能带 i 号物品时,装满包裹的方案总数。
为了美观起见,我们只保留方案数的个位。

示例1

输入

3 2
1 1 2

输出

11
11
21

备注

1n,m2300Ki1000

题解

知识点:背包dp,计数dp。

显然如果不加限制,一遍简单的计数背包dp就能得到所有体积的方案,设状态为 dp[i][j]

但现在要输出不选 i 且体积为 j 的方案数,设其为 f[i][j]。当 j>v[i] ,答案 = 体积为 j 总方案数 - 选 i 且体积为 j 的方案数 = 体积为 j 总方案数 - 不选 i 后体积为 jv[i] 的方案数;当 jv[i] ,答案就是体积为 j 总方案数。因此有公式:

f[i][j]={dp[n][j]f[i][jv[i]],j>v[i]dp[n][j],jv[i]

所以 f[i][j] 可以递推。

时间复杂度 O(nm)

空间复杂度 O(nm)

代码

#include <bits/stdc++.h>
using namespace std;
int k[2307], dp[2307], f[2307];///dp纯0/1背包;不选i时,f[j]表示不选i时体积为j时的方案
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1;i <= n;i++) cin >> k[i];
dp[0] = 1;
for (int i = 1;i <= n;i++)
for (int j = m;j >= k[i];j--)
dp[j] = (dp[j] + dp[j - k[i]]) % 10;
/*
f[j] = 不选i时体积为j的方案
= 体积为j时总方案 - 选i时体积为j的方案
= 体积为j时总方案 - 不选i时体积为j - k[i]的方案
= dp[j] - f[j-k[i]]
当j<k[i]时,dp[j] = f[j] 因为本来就没得选
*/
for (int i = 1;i <= n;i++) {
for (int j = 0;j <= m;j++) {///每次都会覆盖,不需要归零
if (j < k[i]) f[j] = dp[j];
else f[j] = (dp[j] - f[j - k[i]] + 10) % 10;
}
for (int j = 1;j <= m;j++) cout << f[j];
cout << '\n';
}
return 0;
}
posted @   空白菌  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示