CCF 算法竞赛 CACC 实战解析:从报数游戏到资源分配

张开发
2026/4/12 2:51:29 15 分钟阅读

分享文章

CCF 算法竞赛 CACC 实战解析:从报数游戏到资源分配
1. CACC算法竞赛与五道经典题目解析第一次参加CCF算法竞赛CACC时我被其中几道题目深深吸引。这些题目看似简单却蕴含着精妙的算法思想。就像玩魔方一样表面是颜色组合游戏实则考验空间思维和模式识别能力。下面我将分享五道典型题目的解题思路这些经验或许能帮你少走弯路。记得比赛当天我提前半小时到达考场调试好IDE环境。打开题目列表时报数游戏这个标题让我会心一笑——这不就是小时候玩的击鼓传花数字版吗但随后的心智能力和资源分配题目立刻让我意识到这场竞赛远没有表面看起来那么简单。2. 报数游戏约瑟夫问题的实战应用2.1 问题本质与暴力解法题目描述n个同学围坐一圈从1开始报数报到m的同学出局下一位重新从1开始报数直到只剩一人。这实际上是经典的约瑟夫问题。面对n≤1000的数据范围最直接的思路是用环形链表模拟整个过程。我最初尝试用vector实现vectorint circle(n); iota(circle.begin(), circle.end(), 1); // 初始化1~n int pos 0; while(circle.size() 1){ pos (pos m - 1) % circle.size(); circle.erase(circle.begin() pos); } return circle[0];这种方法时间复杂度O(nm)在n1000时完全可行。但要注意vector的erase操作会使后续元素前移时间复杂度是O(n)所以整体复杂度其实是O(n²)。2.2 数学优化与递推公式赛后查阅资料发现约瑟夫问题存在O(n)的递推解int res 0; // f(1,m)0 for(int i2; in; i){ res (res m) % i; } return res 1; // 题目编号从1开始这个解法基于递推关系f(n,m)(f(n-1,m)m)%n其中f(n,m)表示n个人、步长为m时幸存者的初始位置0-based。理解这个公式需要明白每轮游戏本质上是在缩小规模的相同问题上做偏移。3. 宝藏勘探双指针与极值预处理3.1 问题重述与核心难点两位勘探员从数轴两端向中间移动保持至少k单位距离。需要找出他们停留位置组合中覆盖区域的最大最小辐射值差的最小可能。关键在于如何高效计算所有可能停留位置对应的辐射差值。3.2 预处理与滑动窗口优化我的解决方案分为三步预处理四个数组left_min[i]: 位置0~i的最小辐射值left_max[i]: 位置0~i的最大辐射值right_min[i]: 位置i~n的最小辐射值right_max[i]: 位置i~n的最大辐射值vectorint left_min(n), left_max(n); left_min[0] left_max[0] radiation[0]; for(int i1; in; i){ left_min[i] min(left_min[i-1], radiation[i]); left_max[i] max(left_max[i-1], radiation[i]); } vectorint right_min(n), right_max(n); right_min[n-1] right_max[n-1] radiation[n-1]; for(int in-2; i0; --i){ right_min[i] min(right_min[i1], radiation[i]); right_max[i] max(right_max[i1], radiation[i]); }滑动窗口枚举所有可能的分界点x左勘探员停在x右勘探员停在xk1int res INT_MAX; for(int x0; xk1n; x){ int curr_min min(left_min[x], right_min[xk1]); int curr_max max(left_max[x], right_max[xk1]); res min(res, curr_max - curr_min); }考虑右勘探员先出发的情况反向再做一次相同处理。这种方法时间复杂度O(n)空间复杂度O(n)完美处理了n≤10^5的数据规模。4. 心智能力奇偶性操作的位运算优化4.1 问题建模与基础解法题目要求维护两个长度为n的数组支持对指定区间内奇数或偶数元素进行加减操作。直接暴力法是对每个操作遍历区间for(int il; ir; i){ if((arr[i]%2 2)%2 parity){ // parity1操作奇数 arr[i] val; } }这种方法时间复杂度O(qn)在n,q≤10^5时显然会超时。4.2 位运算与差分优化通过分析发现奇偶性变化遵循以下规律奇数±奇数偶数奇数±偶数奇数偶数±奇数奇数偶数±偶数偶数可以用异或运算模拟这个特性int coeff 1 - (a ^ b); // 性质相同为1不同为0基于此我设计了一个差分方案维护两个差分数组一个记录奇数位置操作一个记录偶数位置操作。但实现时发现难以处理操作对元素奇偶性的动态影响最终未能完全解决。赛后了解到这类问题可能需要使用分块懒标记的高级数据结构将区间操作转化为块级别的标记处理。5. 牌型分组贪心策略与特殊规则处理5.1 牌型规则分析题目给出了三种牌型组合方式关键约束是顺子不能包含2和A相邻的情况允许[5,4,3,2,A]这样的特殊顺子牌点大小顺序2 A K Q ... 35.2 贪心算法设计我采用的贪心策略是优先组合顺子5张然后组合三张最后处理对子剩余的单牌中统计比A小的数量实现时需要特别注意特殊顺子的处理// 检查特殊顺子5-4-3-2-A if(count[5] count[4] count[3] count[2] count[14]){ // A记为14 // 组成一组顺子 count[5]--; count[4]--; count[3]--; count[2]--; count[14]--; res; }对于普通顺子需要从大到小检查连续的5个牌点for(int i13; i5; --i){ // 从K开始检查 bool can_form true; for(int j0; j5; j){ if(count[i-j] 0){ can_form false; break; } } if(can_form){ // 组成一组顺子 for(int j0; j5; j) count[i-j]--; res; i; // 重新检查当前位置 } }这个问题的难点在于处理各种边界情况和牌型优先级需要编写大量条件判断代码。6. 资源分配物理机调度算法实战6.1 问题建模与接口设计题目要求实现虚拟机资源调度系统核心操作包括init(n, c, m)初始化n台物理机每台有c个CPU和mGB内存create(vid, vcpu, vmem)创建虚拟机可能需要扩容物理机remove(vid)删除虚拟机释放资源6.2 高效数据结构选择我最终采用了multiset哈希表的方案struct Machine { int pid; int cpu; int mem; bool operator(const Machine other) const { return cpu ! other.cpu ? cpu other.cpu : mem other.mem; } }; struct MachineComp { bool operator()(const Machine a, const Machine b) const { return a.pid b.pid; } }; multisetMachine machines; unordered_mapint, multisetMachine::iterator machine_map; unordered_mapint, int vm_to_pm;6.3 核心算法实现create操作的关键步骤auto it machines.lower_bound(Machine{-1, vcpu, vmem}); if(it machines.end()){ // 需要扩容 Machine new_machine{next_pid, init_cpu, init_mem}; auto ret machines.insert(new_machine); machine_map[new_machine.pid] ret; } Machine allocated *it; machines.erase(it); allocated.cpu - vcpu; allocated.mem - vmem; auto new_it machines.insert(allocated); machine_map[allocated.pid] new_it; vm_to_pm[vid] allocated.pid;remove操作的实现int pid vm_to_pm[vid]; auto it machine_map[pid]; Machine m *it; machines.erase(it); m.cpu vm_resources[vid].cpu; m.mem vm_resources[vid].mem; auto new_it machines.insert(m); machine_map[pid] new_it; vm_to_pm.erase(vid);这种方案保证了O(logn)时间复杂度的资源查找和分配能够处理大规模数据。在实际测试中相比简单的首次适应算法可以节省约15%-20%的物理机使用量。

更多文章