XDU-1036 分配宝藏 (DP)

13 篇文章 0 订阅

1036: 分配宝藏

时间限制:  1 Sec   内存限制:  128 MB
http://acm.xidian.edu.cn/problem.php?id=1036
[ 提交 ][ 状态 ][ 讨论版 ]

题目描述

两个寻宝者找到一个宝藏,里面包含着n件物品,每件物品的价值是w[i]。suma代表寻宝者A所获物品的总价值,sumb代表寻宝者B所获物品的总价值,请问怎么分配,能使得|suma - sumb|(即suma与sumb之差的绝对值)最小。

输入

有多组输入数据,第一行为一个数字T,代表有T组输入数据 (0<T<=50)。
接下来为T组数据,每组数据分为两行:
第一行有一个整数n, 表示物品个数,其中0<n<=200.
第二行有n个整数,第i个正数w[i]代表第i件物品的价值,其中0<w[i]<=200.
注意:所有数据均为正整数。

输出

一共T行。
对于每组数据,输出一个整数,表示|suma-sumb|。

样例输入

2
2
2 3
4
1 2 3 4

样例输出

1
0

sum表示所有物品价值和,则若要两人获得物品的价值差最小,则需要其价值离sum/2最近

设获得物品价值较小的人获得的价值和为x,则x<=sum/2,就可以转为为以sum/2为背包容量的01背包


#include <cstdio>
#include <cstring>

using namespace std;

int T,n,sum,w[205],lim;
bool dp[20005];

int main() {
    while(1==scanf("%d",&T)) {
        while(T-->0) {
            sum=0;
            scanf("%d",&n);
            for(int i=0;i<n;++i) {
                scanf("%d",w+i);
                sum+=w[i];
            }
            lim=sum>>1;//取总和的一半为背包容量上限
            memset(dp,false,sizeof(dp));
            dp[0]=true;
            for(int i=0;i<n;++i) {
                for(int j=lim;j>=w[i];--j) {
                    if(dp[j-w[i]])
                        dp[j]=true;
                }
            }
            for(int i=lim;i>=0;--i) {
                if(dp[i]) {//找到最大的可达到的sum
                    printf("%d\n",sum-i-i);
                    break;
                }
            }
        }
    }
    return 0;
}


  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值