XDOJ 分配宝藏 C

前言

大一蒟蒻,第一篇博客。

初衷:加深理解,举一反三。


题干

问题描述    
两个寻宝者找到一个宝藏,里面包含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|,表示两人所获物品价值总和之差的最小值。

输入样例    
4
1 2 3 4

输出样例    
0


解析

该题核心:0-1背包

以下图片均参考B站up主“麦克老师讲算法”,大家可以看视频来替代理解这些图片,并跳至阅读“转化思路”

https://www.bilibili.com/video/BV1g7411B7SP?from=search&seid=7313354970876638503&spm_id_from=333.337.0.0 

 

 

 

0-1 核心代码: 

for(i=1;i<5;i++){
        for(j=1;j<9;j++){
            if(w[i]>j)
                f[i][j]=f[i-1][j];
            else
                f[i][j]=max(f[i-1][j-w[i]]+w[i],f[i-1][j]);
        }
    }

如何转化是关键!以下是转化思路:

特征(Know)

0-1背包:

     1. 不同物品有重量和价值两个属性

     2. 一人装最大总价值的物品

该题:

  1. 重量与价值一致
  2. 两人装总价值最接近的物品 == 一人装最接近 所有物品总价值的一半 的物品

目标  (Want)

0-1背包:有限容量的背包装最大总价值的物品。

该题:两人所获物品价值总和之差的绝对值|SumA - SumB|最小。

结论  (Learn):三处改动

  1. 不用建数组v[ ]
  2. 答案:f[可供选择的物品件数][总价值的一半]
  3. 当该物品超出总价值的一半,把该物给一人,其余物品给另一人

解答

#include<stdio.h>
int f[201][20001];     //f[可选物品件数][剩余背包容量]
int max(int a,int b);
int main(){
	int n,i,j,tot=0;
	int w[201];            //每件物品的价值,大小记得+1,便于数组下标与物品序号一一对应
	w[0]=0;                
	scanf("%d",&n);
	for(i=1;i<n+1;i++){
		scanf("%d",&w[i]);
		tot+=w[i];
	}
	for(i=0;i<n+1;i++){
		for(j=0;j<tot/2+1;j++){
			f[i][j]=0;
		}
	}
	for(i=1;i<n+1;i++){                  //只需讨论一人的拿法:设该循环讨论的是A,总价值A<=B
		if(w[i]>(tot/2)){                //若有一物超过总价值一半:把该物给B,其余物品均给A 
			f[n][tot/2]=tot-w[i];     
			break;
		}
		for(j=1;j<tot/2+1;j++){          //0-1背包算法
			if(w[i]>j){
				f[i][j]=f[i-1][j];
			}
			else{
				f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+w[i]);
			}
		}
	}
	printf("%d",tot-2*f[n][tot/2]);     //tot-2*f[n][tot/2] == (tot-f[n][tot/2])-f[n][tot/2] 
	return 0;
}
int max(int a,int b){
	int s=a;
	if(b>a) s=b;
	return s;
}

拓展

动态规划 & 贪心算法

https://blog.csdn.net/multiapple/article/details/8852370

https://www.zhihu.com/question/36662980/answer/68494301

我也参考了该问题另一优质详解

https://zhuanlan.zhihu.com/p/340471729

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值