UVALive5583 UVA562 Dividing coins

本文介绍了一个经典的算法问题——如何将一组金币分为两堆使它们的总价值最接近。通过使用0/1背包问题的动态规划方法解决了这个问题,并给出了详细的算法解释和C语言实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}


转载于:https://www.cnblogs.com/tigerisland/p/7564410.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值