uva562 - Dividing coins(简单动规)

本文介绍了一种解决01背包问题中寻找最接近总和一半的子集的方法。通过动态规划枚举所有可能的子集,找到使两组元素之差最小的组合。文章给出了具体的C++实现代码,并提出了优化遍历过程的方法。

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

找平衡的01背包问题。。。。

开始的时候不知道怎么直接动规出答案,

后来人家的思路,才发现这道题可以间接的动规出来答案。

就是把sum求出来,然后用动规枚举所有组合情况。然后找最小的sum-ii的差值,min{sum-i-i}

这道题有sum==i的情况。

1

1

5

答案应该是5

所以最后找的时候要从0--sum遍历。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#define M 50005
#define N 105
#define INF 0x7fffffff
int n, v[N];
bool f[M];

int main ()
{
    int cas, sum;
    scanf("%d",&cas);
    while(cas--)
    {
        sum = 0;
        scanf("%d",&n);
        for(int i = 0; i < n; i++) {scanf("%d",&v[i]); sum+=v[i];}
        memset(f,0,sizeof(f));
        f[0] = 1;
        for(int i = 0; i < n; i++)
            for(int j = sum; j >= v[i]; j--)  if(f[j-v[i]])
            f[j] = 1;
        int min = INF;
        for(int i = 0; i <= sum; i++) if(f[i])
        {
            int tt = abs(sum-i-i);
            min = min > tt ? tt : min;
        }
        printf("%d\n",min);
    }
    return 0;
}


 

最后的遍历可以优化。

for(int i = sum/2; i >= 0; i--)
        if(f[i]) {min = i; break; }
        printf("%d\n",sum-2*min);


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值