砝码称重问题——未经优化的01背包解法

题目连接 洛谷P2347

题目描述

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重≤1000 ),
输入格式

输入方式:a1,a2,a3,a4,a5,a6

(表示1g砝码有a1​个,2砝码有a2​个,…,20g砝码有a6​个)
输出格式

输出方式:Total=N

(N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)

首先拿到题目,尝试枚举法,结果超时。

之后分析问题:
题目给了一些物品,给了总空间1000,并且有权值和重量两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选两种情况。如果不选择将其放入背包中,则不需要处理。

动态转移方程 f[i][j] = f[i-1][j] || f[i-1][j-weight[i]]
这里的i指的是第i个砝码,比如数据1 2 3 4 5 6,i = 4的时候就是指第一个重量为3的砝码 f是用于标记我们是不是访问过这个状态
j指的就是重量,指前i个砝码放上去的总重量是多少。

我认为01背包本质上是利用数组把之前算过的部分算了,进而减少运算次数。把上一次的状态记好,存下来,再有重复的时候可以直接调出来。
因为本题没有说要求最大的情况,而是说要求所有次数。所以状态转移方程并不是用max{f[n], f[n-1]},而是根据之前枚举的所有状态来推得能否得到现在的状态。
在代码书写时我出现了一个问题,开始我是遍历了所有flag数组去求解类别,后来发现只要遍历i=n的时候就可以了,因为因为之前的(比如当i=1时,j=1这种情况就是我拿了一个1g的砝码,然而flag[2][1]也是一样的,相当于没放2g的砝码,但是最后的重量都是1)。
原来的解法打了注释(结果还是不对,开了个数组保证weight的唯一性,但好像不行)

// 01背包实现砝码称重问题
// 本质上是利用数组把之前算过的部分算了,进而减少运算次数。把上一次的状态记好,存下来,再有重复的时候可以直接调出来。
// 因为本题没有说要求最大的情况,而是说要求所有次数。所以状态转移方程并不是用max{f[n], f[n-1]},而是根据之前枚举的所有状态来推得能否得到现在的状态。
// 状态转移方程应该是 f[i][j] = f[i-1][j] || f[i-1][j-weight[i]],若这两个状态可以达到,那么f[i][j]的状态也就可以达到。
#include <stdio.h>
int flag[1100][1100] = {
   0};
int weight[1100] = {
   0};
int val[1100] = {
   0};
int main(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值