java动态规划 硬币 牛客_动态规划之牛客网例题

小Q是篮球训练队的教练,篮球队新加入了N名队员,第i名队员的篮球水平值为ai。

小Q现在要把他们按照以下的要求分为A队和B队进行训练:

1、A队的队员水平值之和严格大于B队的队员水平值之和

2、对于A队中的任意一名队员,如果把他分配到B队,A队的水平值之和就会严格小于B队的水平值之和。

3、每个队员必须要加入一个队伍

小Q现在想知道有多少种方案可以按照以上要求完成分队。

输入:

5  6 7  4

输出:

2

第一眼的两个思路:

使用DFS求解,不过大多笔试题都不会使用这种算法求解,通过率很低。

求出所有组合的和,组成一个数组。但是想不出动态规划的方法

本题思路:

定义一个数组,数组长度为sum(所有元素的和)+1的长度。该数组的索引为组合求和的值,数组的

将数组从大到小排序

将每一个数依次做为A中的最小值,则比这个数小的都必定在B中,对比这个数大的使用01背包进行动态规划求解。求各数相加的和等于array中的索引值的种类,再判断索引值是否满足题目题目约束的A队和B对的关系。

代码:

#include#include#includeusing namespace std;

int main() {

int n;

cin >> n;

vectora(n);

long long sum = 0;

for (int i = 0; i < n; i++) {

cin >> a[i];

sum = sum + a[i];

}

sort(a.begin(), a.end());

reverse(a.begin(), a.end());//从大到小排序

vectorarray(sum+1, 0);

array[0] = 1;

long long res = 0;

for (int i = 0; i < n; i++) {//a[i]为最小的摇摆点,所以之前的a[i]要从大到小排序

for (long long end = sum; end >= a[i]; end--) {

array[end] = array[end] + array[end - a[i]];

if ((end > sum - end) && ((end - a[i]) < (sum - end + a[i]))) {

res += array[end - a[i]];//注意这里是array[end-a[i]],以免重复计算

}

}

}

cout << res << endl;

cin >> n;

return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值