UVALive5583 UVA562 Dividing coins【0/1背包+DP】

It’s commonly known that the Dutch have invented copper-wire. Two Dutch men were fighting overa nickel, which was made of copper. They were both so eager to get it and the fighting was so fierce,they stretched the coin to great length and thus created copper-wire.

  Not commonly known is that the fighting started, after the two Dutch tried to divide a bag withcoins between the two of them. The contents of the bag appeared not to be equally divisible. The Dutchof the past couldn’t stand the fact that a division should favour one of them and they always wanteda fair share to the very last cent. Nowadays fighting over a single cent will not be seen anymore, butbeing capable of making an equal division as fair as possible is something that will remain importantforever...

  That’s what this whole problem is about. Not everyone is capable of seeing instantly what’s themost fair division of a bag of coins between two persons. Your help is asked to solve this problem.

  Given a bag with a maximum of 100 coins, determine the most fair division between two persons.This means that the difference between the amount each person obtains should be minimised. Thevalue of a coin varies from 1 cent to 500 cents. It’s not allowed to split a single coin.

Input

A line with the number of problems n, followed by n times:

  • a line with a non negative integer m (m ≤ 100) indicating the number of coins in the bag

  • a line with m numbers separated by one space, each number indicates the value of a coin.

Output

The output consists of n lines. Each line contains the minimal positive difference between the amountthe two persons obtain when they divide the coins from the corresponding bag.

Sample Input

2

3

2 3 5

4

1 2 4 6

Sample Output

0

1

 

Regionals 1996 >> Europe - Northwestern

 

问题链接UVALive5583 UVA562 Dividing coins

问题简述

  输入测试用例数n,每个测试用例包括金币的数量m和m个正整数是金币的币值。将这些金币分为两堆,使得其差值最小,求最小的差值。

问题分析

  可以用0/1背包的动态规划方法来解决这个问题。将背包的容量设为所有金币币值之和的一半,将这一堆金币尽可能多地放入背包即可。再计算一下差值即可。

  0/1背包动态规划法的递归式为f(j,X),其中j=0,1,2,...,n-1为物品(共n个物品),X是背包的载重量。f(j,X)的含义为:当背包载重为X,可供选择的物品为0,1,2,...,j时的最优值。具体式子如下:

  f(-1,X)=-∞(X<0),f(-1,X)=0(X>=0)

  f(j,X)=max{f(j-1,X), f(j-1(X-wj)+pj} 0<=j<n,wj为第j件物品重量,pj为第j件物品收益。

程序说明

  程序中,用二维数组dp[][]来存放递推函数的值,比较浪费存储空间,应该使用STL构筑一个稀疏矩阵来存储比较合理。

  另外,wj=coin[j]即币值,pj=coin[j]即币值,一种特例情况。程序逻辑实际上是套用0/1背包递推函数。

 

AC的C语言程序如下:

 

/* UVALive5583 UVA562 Dividing coins */

#include <stdio.h>
#include <memory.h>

#define MAX(x, y) (((x)>(y))?(x):(y))

#define MAXN 100

int dp[MAXN+1][MAXN * 500];

int main(void)
{
    int t, m, coin[MAXN+1], sum, sum2, i, j;

    scanf("%d", &t);
    while(t--) {
        scanf("%d", &m);

        memset(coin, 0, sizeof(coin));
        memset(dp, 0, sizeof(dp));

        sum = 0;
        for(i=1; i<=m; i++) {
            scanf("%d", &coin[i]);
            sum += coin[i];
        }


        sum2 = sum / 2;
        for(i=1; i<=m; i++)
            for(j=0; j<=sum2; j++)
                if(j >= coin[i])
                    dp[i][j] = MAX(dp[i - 1][j], (dp[i - 1][j - coin[i]] + coin[i]));
                else
                    dp[i][j] = dp[i - 1][j];

        printf("%d\n", sum - dp[m][sum2] - dp[m][sum2]);
    }

    return 0;
}

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值