hdu 5000 dp+推导结论

本文探讨了如何使用动态规划解决背包问题中的子集选择问题,旨在找出具有特定属性和的子集组合,使得这些组合能够最大化地满足特定条件,并通过代码实现了这一过程。

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

首先我们考虑什么情况能够得到最多的情况:

1.首先如果两个人的各项属性之和相同,且并非每一项都相同,那么他们必定至少有一项大于对方,且有一项小于对方.所以和相等的能够组成不同的情况

2.再考虑,当两个人的各项属性之和不相等却符合题设要求的时候,设他们为a和b,那么一定存在和a总和相等的c,且c与b矛盾,因为c可以所有项与b相同,仅有一项不等于b(那么必然矛盾),或者说c的一项属性为0的时候,依旧不能让其他属性和b相等,那么必然矛盾,所以选取b会导致c不能选,所以不会影响最终结果,所以最终选取最多的情况一定是所有情况的和相同.

3.因为要取模,所以不能在算完结果后再比较大小,所以只能预判,也就是要得到最大情况,我们要取的是和为sumT[i]/2的选取方案,因为和取sum/2时,取所有数取平均数为基准,当和为sum/2时才可以,在这个时候每个数通过增减获得异于它本身的方案数是最多的

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 2007
#define MOD 1000000007

using namespace std;

typedef long long LL;

int t,n;
LL dp[MAX][MAX];
int a[MAX];

int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d" , &n );
        int sum = 0;
        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%d" , &a[i] );
            sum += a[i];
        }
        memset ( dp , 0 , sizeof ( dp ) );
        dp[0][0] = 1;
        for ( int i = 1 ; i <= n ; i++ )
            for ( int j = 0 ; j <= a[i] ; j++ )
                for ( int k = j ; k <= sum/2 ; k++ )
                    dp[i][k] = ( dp[i][k] +  dp[i-1][k-j] )%MOD;
        printf ( "%lld\n" , dp[n][sum/2] );
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值