题目
题目链接
题解动态规划。
状态定义:dp[i][j]
表示前i
个砝码是否能称出重量为j
的物品。
状态转移:对于第i
个砝码,选和不选两种情况;对于选又可以分为放在左边和放在右边。
看样例,存在加和减的情况,也就是放在左边和右边的情况。我们规定放在左边用加表示,放在右边用减表示。
那么第i
个砝码的全部情况为第i
个砝码不放、放左边或放右边。对于重量为j
的物品,如果不放第i
个砝码,则dp[i][j] |= dp[i-1][j]
,即若用i-1
个砝码可以称出j
,那么用i
个砝码肯定也行;如果将第i
个砝码放在左边(正),那么用i-1
个砝码只需要能称出j-w[i]
的物品即可,所以dp[i][j] |= dp[i-1][j-w[i]]
;类似地,将第i
个砝码放在右边(负),那么dp[i][j] |= dp[i-1][j+w[i]]
存在一个问题,如此定义转移方程会存在全部砝码全放在左侧或全放在右侧的情况,也就是说会出现负数作为索引的情况。
为了避免这种情况,我们让索引加上一个大数来保证索引为正值。
最后统计能称出不同重量的物品数量时,只需要让j
从1
变化到最大值即可,因为k
表示左边-右边=k
,即右边与左边之差为k
;-k
表示右边-左边=k
,即左边与右边之差为k
,本质上都是表示能称出重量为k
的物品的意思。所以如果左侧的也统计则相当于统计了两遍。
#include
using namespace std;
const int N = 1e5+10;
const int Bais = N;
int n, a[N], ans, m;
bool f[110][N n;
for (int i = 1;i > a[i], m += a[i];
f[0][Bais] = true; // 用0个砝码称出重量为0的物品
for (int i = 1;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?