NC19158 失衡天平
题目
题目描述
终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平的两端,若天平平衡则可以将天平上的所有武器拿走,还好这个天平锈迹斑斑,只要两端重量相差小于等于m就会保持平衡,Alice傻傻的认为越重的武器越好,求Alice最多能拿走的武器总重量。(不限操作次数)
输入描述
第一行2个整数 n, m;
第二行n个整数x,分别表示n件武器的重量。
1 <= n <= 100; 0 <= m <= 100; 1 <= x <= 100;
输出描述
一个整数,表示Alice最多能拿走的武器总重量。
示例1
输入
5 4 1 5 61 65 100
输出
132
说明
可以称两次,第1次:(1 ; 5),第二次(61 ; 65)。
示例2
输入
5 0 10 20 30 40 100
输出
200
说明
称一次,(10,20,30,40 ; 100)。
题解
知识点:背包dp。
01背包变种。设 为考虑了 个物品天平两遍差的绝对值为 的最大值。因为天平左右两边可以随时互换,我们只考虑绝对值即可。转移方程为:
注意边界,而且 的范围应该是 ,而不是 ,因为可以放天平另一端平衡。
最后找到 的最大值即可。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int dp[107][10007], w[107]; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n, m, sum = 0; cin >> n >> m; for (int i = 1;i <= n;i++) cin >> w[i], sum += w[i]; memset(dp, -0x3f, sizeof(dp));///必须负无穷,不能填空气,因为可能导致所有物品都能放 dp[0][0] = 0; for (int i = 1;i <= n;i++) { for (int j = 0;j <= sum;j++) { ///不能到m就结束,因为可能从后面传递 dp[i][j] = dp[i - 1][j]; if (j + w[i] <= sum) dp[i][j] = max(dp[i][j], dp[i - 1][j + w[i]] + w[i]); if (abs(j - w[i]) <= sum) dp[i][j] = max(dp[i][j], dp[i - 1][abs(j - w[i])] + w[i]); } } int ans = 0; for (int i = 0;i <= m;i++) ans = max(ans, dp[n][i]); cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16581350.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧