XDOJ 174分配宝藏 dp01背包



、# XDOJ 174题分配宝藏(动态规划01背包拓展

本文章仅解释本题思路,(本文假设读者已经了解01背包)。关于动态规划详细解答请参考博客XDOJ(智慧平台)–分配宝藏(用动态规划dp算法解决)(C语言)。关于01背包还有这个比较详细的b站视频动态规划dp01背包


题目描述

标题
分配宝藏
类别
综合
时间限制
2S
内存限制
256Kb
问题描述
两个寻宝者找到一个宝藏,里面包含n件物品,每件物品的价值分别是W[0],W[1],…W[n-1]。
SumA代表寻宝者A所获物品价值总和,SumB代表寻宝者B所获物品价值总和,请问怎么分配才能使得两人所获物品价值总和差距最小,即两人所获物品价值总和之差的绝对值|SumA - SumB|最小。

输入说明

输入数据由两行构成:
第一行为一个正整数n,表示物品个数,其中0<n<=200。
第二行有n个正整数,分别代表每件物品的价值W[i],其中0<W[i]<=200。

输出说明

对于每组数据,输出一个整数|SumA-SumB|,表示两人所获物品价值总和之差的最小值。

输入样例

1 2 3 4

输出样例

0

思路

1.从分配价值总和可以看出这题是个01背包问题。

2.背包是什么呢?物品是什么呢?价值、重量分别对应什么呢?

3.题目中说两人价值总和之差最小,不妨设价值之差最小时A的价值为sum[a],B的价值为sum[b],(且sum[a] < sum[b]),价值总和为SUM。

4.由数学知识可以知道,sum[a] - sum[b]的绝对值要最小,就要使SUM - sum[a]的值最小。

5.这步是关键点。由上面题意可以知道,要使得SUM - sum[a]的值最小,换句话说就是在 ⌊ S U M 2 ⌋ \lfloor \frac{SUM}{2} \rfloor 2SUM(向下取整)范围内,sum[a]能分配到的最大价值。那么就找到背包和价值了:
a的价值就是背包, ⌊ S U M 2 ⌋ \lfloor \frac{SUM}{2} \rfloor 2SUM就是背包容量,宝藏的价值既是物品的价值,也是物品的重量



那么就可以给出代码

#include <iostream>
#include <algorithm>
using namespace std;
int main(){
	int n, sum=0;
	int w[201], dp[20001] = {0};// w[]:宝藏价值。dp[]:A分到的宝藏价值
	cin >> n;
// 读取数据
	for (int i = 0; i < n; i++) {
		cin >> w[i];
		sum += w[i];
	}
// 处理数据
				/*状态转移公式为:dp[j] = max(dp[j], dp[j-w[i]] + w[i])
				这里w[i]既是重量,也是价值*/
	int target = sum/2;  // target 是目标的背包容量
	for (int i = 0; i < n; i++)
		for (int j = target; j >= w[i]; j--)
			if (w[i] <= j)
				dp[j] = max(dp[j], dp[j-w[i]]+w[i]);
// 输出数据
	cout << sum-dp[target]-dp[target]; 
	//sum-dp[target]就是目标状态下B分到的价值,
	//dp[target]就是目标状态下A分到的价值。
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值