[Acwing蓝桥杯DP] 3417. 砝码称重
题目大意:有n个砝码,放在天平两侧,天平左边加重量,右边减重量,问这些砝码能凑出来多少正整数重量。
数据范围:1<=n<=100,这些砝码的总质量m<=1e5
分析:
这是个经典的01背包变形问题。
用闫氏DP分析法:
集合:f [ i ][ j ] 表示: 在前n个砝码中选择的重量为j的方案是否存在
属性:bool 是否存在
方式划分:关于第n个砝码(1)第n个砝码不选
(2)第n个砝码选,放左边 加w[n]
(3)第n个砝码选,放右边 减w[n]
状态转移:f [ i ][ j ] = f [ i - 1 ][ j ]
f [ i ][ j ] |= f [ i - 1][ j - w[ i ] ] , f [ i ][ j ] |= f [ i-1 ][ j +w[ i ] ];
初始化:f [ 0 ][ 0 ]=1;
ps:注意找个题重量要从 -m枚举倒+m ,由于集合的变量下标不能为负数,我们要将所有的重量加上一个偏移量,防止出现负数
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=110,M=2e5+10,B=M/2;
int n,m;
int w[N];
bool f[N][M];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&w[i]),m+=w[i];
f[0][0+B]=1;
for(int i=1;i<=n;i++)
{
for(int j=-m;j<=m;j++)
{
f[i][j+B]=f[i-1][j+B];
if(j+w[i]<=m)f[i][j+B]|=f[i-1][j+w[i]+B];
if(j-w[i]>=-m)f[i][j+B]|=f[i-1][j-w[i]+B];
}
}
int res=0;
for(int i=1;i<=m;i++)
{
if(f[n][i+B])res++;
}
printf("%d",res);
return 0;
}
END!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人