[Acwing蓝桥杯DP] 3417. 砝码称重

题目链接:3417. 砝码称重 - AcWing题库

题目大意:有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!!!

 

posted @   秦末  阅读(77)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
1 博文导航目录
点击右上角即可分享
微信分享提示