算法实战:牛客14777题足球积分分配问题的数学建模与枚举解法
一、问题背景与理解
牛客14777题要求判断在给定的比赛场次(n)、已比赛场次(k)和两队分差(d1,d2)条件下,是否存在合理的积分分配方案。这是一个典型的数学建模与枚举验证问题。
二、完整代码实现(带详细注释)
#include <iostream> #include <cmath> using namespace std; bool check(long long n, long long k, long long d1, long long d2) { // 特殊情况处理:比赛已结束 if (k == 0) return (n % 3 == 0); // 未开始比赛需能均分 if (n == k) return (d1 == 0 && d2 == 0); // 比赛结束应无分差 long long total = n * 3; // 总积分 long long remaining = n - k; // 剩余比赛场次 // 枚举4种可能的比分组合 for (int s1 : {-1, 1}) { // 第一组分差方向 for (int s2 : {-1, 1}) { // 第二组分差方向 long long sum = 2 * s1 * d1 + s2 * d2; if ((k - sum) % 3 != 0) continue; // 积分需能被3整除 long long a = (k - sum) / 3; // 队A积分 long long b = a + s1 * d1; // 队B积分 long long c = b + s2 * d2; // 队C积分 // 检查非负性 if (a < 0 || b < 0 || c < 0) continue; // 计算需要调整的分数 long long max_score = max(a, max(b, c)); long long needed = (max_score - a) + (max_score - b) + (max_score - c); // 检查剩余比赛是否足够 if (needed <= remaining && (remaining - needed) % 3 == 0) { return true; } } } return false; } int main() { ios::sync_with_stdio(false); // 加速输入输出 cin.tie(nullptr); int t; // 测试用例数 cin >> t; while (t--) { long long n, k, d1, d2; cin >> n >> k >> d1 >> d2; cout << (check(n, k, d1, d2) ? "yes" : "no") << endl; } return 0; }
三、算法核心思想
数学建模:将问题转化为三元一次方程组求解
枚举验证:尝试4种可能的分差组合方向
边界检查:确保积分非负且剩余比赛足够调整
整除验证:保证所有积分分配方案合法
四、复杂度分析
时间复杂度:O(1) - 固定4次枚举循环
空间复杂度:O(1) - 仅使用常数空间
五、关键技巧
分差方向的正负枚举
积分调整量的计算
剩余比赛场次的合理分配
特殊情况的提前处理
参考:牛客14777题解
原创内容 转载请注明出处