洛谷 2663 越越的组队 【dp】

本文介绍了一个通过01背包问题解决的班级综合能力竞赛分组算法。该算法旨在将班级同学分成实力接近的两队,确保比赛公平。通过计算成绩之和在不超过班级总分一半的前提下尽可能达到最高值。

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


题目描述

班级要组织一场综合能力竞赛,全班同学(N(100以内)个,N是偶数)分成两队互相竞争。老师找到了越越并给了越越一张全班同学综合能力测试的成绩,要求他从全班同学中选出一半(他自己也可能被选),并要求这些同学综合能力测试的成绩之和在不超过班级总分一半的前提下尽量达到最高。这样分成的两队实力是最平均的。越越堆着满脸的笑容找到了你,你就帮他写一个程序吧。

输入输出格式

输入格式:

第一行:学生个数N;第二行开始的N行每行一个同学的综合能力测试的成绩。

输出格式:

输出一个数:N/2个同学的综合能力测试的成绩之和在不超过班级总分一半的前提下尽量达到的最高值。

输入输出样例

输入样例#1:


8
77
77
56
77
84
77
56
46
输出样例#1:

273
每次取总数的一半!   0 1 背包


#include <iostream>
#include <algorithm>
using namespace std;
int w[10000],dp[10000],n,i,j,sum,t;
int main(){
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>w[i];
        sum+=w[i];
    }
    t=sum/2;
    for(i=1;i<=n;i++)
        for(j=t;j>=w[i];j--)
            dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
    cout<<dp[t]<<endl;
}










``` #include <iostream> #include <cstdio> using namespace std; int n; int a[107]; int dp[107][10007]; int sum; inline int maxa(int a, int b) { if (a > b) return a; return b; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i ++) { scanf("%d", &a[i]); sum += a[i]; } dp[0][0] = 1; for (int i = 1; i <= n; i ++) { for (int j = i; j >= 1; j --) { for (int k = sum >> 1; k >= a[i]; k --) dp[j][k] |= dp[j - 1][k - a[i]]; } } for (int i = sum >> 1; i >= 0; i --) { if (dp[n >> 1][i]) { printf("%d\n", i); return 0; } } }```# P2663 组队 ## 题目描述 班级组织一场综合能力竞赛班里共有 $n$ 学生,将分成两队互相竞争老师找到并给了一张全班同学综合能力测试的成绩,要求他从全班同学中选出**一半**,并要求这些同学综合能力测试的成绩之和在**不超过班级总分一半**的前提下尽量达到最高。这样分成两队实力是最平均的。堆着满脸的笑容找到了你,你就帮他写一个程序吧。 ## 输入格式 第一行有一个整数,表示班级学生人数 $n$。 第 $2$ 到第 $(n + 1)$ 行,每行一个整数,第 $(i + 1)$ 行的整数 $a_i$ 表示第 $i$ 同学的成绩。 ## 输出格式 输出一行一个整数表示答案。 ## 输入输出样例 #1 ### 输入 #1 ``` 8 77 77 56 77 84 77 56 46 ``` ### 输出 #1 ``` 273 ``` ## 说明/提示 #### 样例 1 解释 班级总分为 $550$,总分的一半是 $275$,选则成绩分别为 $56,77,84,56$ 的同学可以达到总分 $273$,是不超过 $275$ 的最大值。 #### 数据规模与约定 对于全部的测试点,保证 $1 \leq n \leq 100$,$0 \leq a_i \leq 100$,数据保证 $n$ 均为偶数。
03-08
``` #include<bits/stdc++.h> using namespace std; int a[200]; //dp[i][j][k] 前i个数,当前在第i个数,已经选中了j个,容量为k的最大价值 int dp[200][200][200]; int sum; int ans; int main(){ // freopen("test.in", "r", stdin); // freopen("test.out", "w", stdout); int n; cin>>n; for(int i = 1; i <= n; i++) { for(int j = 0; j <= n; j++) { for(int k = 0; k <= 10000; k++) { dp[i][j][k] = -10000; } } } for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } sum/=2; // for(int k = a[1]; k <= sum; k++) { // dp[1][1][k] = a[1]; // } for(int i=1;i<=n;i++){ for(int j=1;j<=min(i,n/2);j++){ for(int k=0;k<=sum;k++){ dp[i][j][k]=dp[i-1][j][k]; if(j == 1 && k>=a[i]) { dp[i][j][k] = max(dp[i][j][k], a[i]); } if(k>=a[i]) { // if(dp[i-1][j-1][k-a[i]] == -10000) continue; dp[i][j][k]=max(dp[i-1][j-1][k-a[i]]+a[i],dp[i][j][k]); } } } // cout << "前" << i << "个数:\n"; // for(int j = 1; j <= n/2; j++) { // for(int k = 0; k <= sum; k++) { // cout << dp[i][j][k] << " "; // } // cout << endl; // } // cout << endl; } // for(int i = 1; i <= n; i++) { // // } // n/=2; for(int i=1;i<=n;i++){ ans=max(dp[i][n/2][sum],ans); } cout<<ans; return 0; }```班级组织一场综合能力竞赛班里共有 n 学生,将分成两队互相竞争老师找到并给了一张全班同学综合能力测试的成绩,要求他从全班同学中选出一半,并要求这些同学综合能力测试的成绩之和在不超过班级总分一半的前提下尽量达到最高。这样分成两队实力是最平均的。堆着满脸的笑容找到了你,你就帮他写一个程序吧。
最新发布
03-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值