1 条题解
-
0
解题思路:
本题要求将参赛者分成两队,使得两队人数差不超过1,且总重量尽可能接近。通过动态规划的方法,将问题转化为“限定人数下的背包问题”,寻找最优分配方案。
关键步骤:
- 总重量计算:计算所有人体重的总和,确定目标为寻找最接近总和一半的重量。
- 动态规划定义:定义 表示选 个人是否能组成总重量 。
- 状态转移:遍历每个人,更新可能的选人数量 和对应重量 ,标记可达状态。
- 寻找最优解:在允许的最大人数范围内,从总和的一半开始向下查找最大的可行重量。
- 结果输出:确保输出时较小值在前,较大值在后。
实现细节:
- 人数限制处理:通过 控制两队人数差不超过。
- 动态规划优化:遍历顺序确保状态更新正确,避免重复计算。
- 目标范围剪枝:仅搜索 到 的重量范围,缩小计算规模。
特殊情况处理:
- 当 时,直接输出该人体重和。
- 当总重量为奇数时,优先选择接近较大值的一侧。
C++实现:
#include <cstdio> #include <algorithm> using namespace std; int n, sum; int a[500]; // 存储每个参赛者的体重 int dp[110][110 * 500];// dp[j][k]表示选j个人是否能组成总重量k int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum += a[i]; // 计算总重量 } // 初始化:选0个人组成0重量的状态为可行 for (int j = 0; j <= (n + 1) / 2; j++) dp[j][0] = 1; // 动态规划状态转移 for (int i = 1; i <= n; i++) { // 遍历每个参赛者 for (int j = (n + 1) / 2; j >= 1; j--) { // 逆序处理人数,防止重复选人 for (int k = sum / 2; k >= a[i]; k--) { // 遍历可能的重量 if (dp[j - 1][k - a[i]]) { // 若前一步状态可达 dp[j][k] = 1; // 标记当前状态可达 } } } } // 寻找最大可行重量 int ans = sum / 2; while (ans >= 0) { if (n % 2 == 0 && dp[n / 2][ans]) break; // 偶数人数需选n/2人 if (n % 2 == 1 && (dp[(n + 1) / 2][ans] || dp[n / 2][ans])) break; // 奇数人数允许两种人数 ans--; } int ansmin = sum - ans; if (ansmin < ans) swap(ansmin, ans); // 确保较小值在前 printf("%d %d\n", sum - ansmin, ansmin); return 0; }
- 1
信息
- ID
- 1577
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者