news 2026/4/15 15:01:48

暴力枚举法解决环形石子合并问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
暴力枚举法解决环形石子合并问题

暴力枚举法解决环形石子合并问题:原理、代码与分析
一、问题引入
石子合并问题是区间动态规划的经典案例,而 “环形石子合并” 是其进阶形式:
在圆形操场的四周有 n 堆石子,每次只能合并相邻的两堆,合并得分是新堆的石子数。求将所有石子合并成一堆的最小得分和最大得分。
二、暴力枚举法的核心思路
暴力枚举法的本质是穷举所有可能的合并顺序,计算每种顺序的得分,最终取极值。
由于石子是环形排列,我们需要先将其转化为线性数组(拼接原数组,覆盖所有环形起点),再对每个线性子数组枚举所有合并顺序:
环形转线性:将原数组 stones 拼接一份(如 [4,1,2,3] → [4,1,2,3,4,1,2,3]),枚举所有长度为 n 的子数组,等价于枚举环形的所有起点。
枚举合并顺序:对每个线性子数组,递归枚举所有 “合并相邻堆” 的可能顺序,累计得分,最终记录全局最小 / 最大值。
三、C++ 代码实现(详细注释)
cpp
运行
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;

// 全局变量:记录全局最小/最大得分
int global_min = INT_MAX;
int global_max = INT_MIN;

/**
* 递归暴力枚举所有合并顺序
* @param stones 当前剩余的石子堆数组
* @param current_score 当前累计的合并得分
*/
void bruteForceMerge(vector<int>& stones, int current_score) {
// 递归终止条件:只剩1堆石子,更新全局得分
if (stones.size() == 1) {
global_min = min(global_min, current_score);
global_max = max(global_max, current_score);
return;
}

// 枚举所有相邻的两堆,尝试合并
for (int i = 0; i < stones.size() - 1; ++i) {
// 1. 记录原始值(用于回溯)
int a = stones[i], b = stones[i + 1];
int merge_score = a + b; // 本次合并的得分

// 2. 原地合并:修改i位置,删除i+1位置
stones[i] = merge_score;
stones.erase(stones.begin() + i + 1);

// 3. 递归处理合并后的新数组
bruteForceMerge(stones, current_score + merge_score);

// 4. 回溯:恢复数组状态(保证其他分支的独立性)
stones.insert(stones.begin() + i + 1, b);
stones[i] = a;
}
}

int main() {
int n;
cout << "请输入石子堆数 n:";
cin >> n;

vector<int> stones(n);
cout << "请输入 " << n << " 堆石子的数量:";
for (int i = 0; i < n; ++i) {
cin >> stones[i];
}

// 环形转线性:枚举所有起点(覆盖环形的所有可能起始位置)
for (int start = 0; start < n; ++start) {
vector<int> linear_stones;
for (int i = 0; i < n; ++i) {
// 取模实现环形遍历,start为起点,i为偏移量
linear_stones.push_back(stones[(start + i) % n]);
}
// 对当前线性子数组枚举所有合并顺序
bruteForceMerge(linear_stones, 0);
}

// 输出结果
cout << "暴力枚举法最小得分:" << global_min << endl;
cout << "暴力枚举法最大得分:" << global_max << endl;

return 0;
}
四、代码运行示例
输入:
plaintext
请输入石子堆数 n:4
请输入 4 堆石子的数量:4 1 2 3
输出:
plaintext
暴力枚举法最小得分:19
暴力枚举法最大得分:26
五、暴力枚举法的优缺点分析
优点
逻辑直观:完全贴合 “合并相邻堆” 的规则,结果绝对正确,适合理解问题本质;
实现简单:无需复杂的动态规划或分治思想,仅需递归 + 枚举即可完成。
缺点
时间复杂度极高:
O(n×n!)
(n 为石子堆数),n=6 时需枚举约 720 种合并顺序,n=7 时需 5040 种,n>8 时几乎无法运行;
实用性差:仅能处理极小规模用例,无法应用于实际场景。
六、暴力法的优化方向
暴力法的核心问题是 “重复计算” 和 “阶乘级复杂度”,实际应用中需放弃暴力枚举,改用更高效的算法:
记忆化搜索:缓存 “合并区间 [i,j] 的得分”,时间复杂度降至 O(n 3);
区间动态规划:自底向上计算区间最优解,是环形石子合并的标准最优解法,时间复杂度O(n 3 ),可处理 n≤200 的大规模用例。
七、总结
暴力枚举法是理解 “石子合并问题” 的入门方式,但其阶乘级的时间复杂度决定了它仅适用于学习阶段。实际开发中,我们通常会使用区间动态规划来解决环形石子合并问题,既保证效率,又能得到全局最优解。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 15:01:44

R Shiny中实现图表与控件实时通信的秘技(仅限高级用户参考)

第一章&#xff1a;R Shiny中实现图表与控件实时通信的秘技&#xff08;仅限高级用户参考&#xff09;在构建交互式数据仪表板时&#xff0c;实现图表与控件之间的深度联动是提升用户体验的关键。R Shiny 提供了强大的响应式编程模型&#xff0c;使得 UI 组件与后端逻辑能够无缝…

作者头像 李华
网站建设 2026/4/15 10:34:48

Dify部署实战:用Qwen3-8B构建企业级对话机器人

Dify部署实战&#xff1a;用Qwen3-8B构建企业级对话机器人 在智能客服、内部知识助手和自动化办公日益普及的今天&#xff0c;越来越多企业希望拥有一个既懂业务又能“说人话”的AI对话系统。然而&#xff0c;现实往往令人却步&#xff1a;一边是调用大厂API带来的高昂成本与数…

作者头像 李华
网站建设 2026/4/15 13:30:39

揭秘低代码平台中PHP组件兼容性陷阱:90%开发者忽略的2个细节

第一章&#xff1a;低代码平台中PHP组件兼容性的核心挑战在低代码开发环境中&#xff0c;PHP作为后端逻辑的重要实现语言&#xff0c;其组件的兼容性问题日益凸显。由于低代码平台通常封装了底层运行时环境&#xff0c;开发者对PHP版本、扩展模块及依赖库的控制能力被大幅削弱&…

作者头像 李华
网站建设 2026/4/11 13:02:54

zookeeper基础概念及集群部署

目录 前言&#xff1a; 一.Zookeeper 概述 二.Zookeeper 工作机制 三.Zookeeper 特点 四.Zookeeper 数据结构 五.Zookeeper 应用场景 六.zookeeper选举机制 1.第一次启动选举机制 2.非第一次启动选举机制 七.部署 Zookeeper 集群 1.部署环境ZK 2.安装前准备 3.安装…

作者头像 李华
网站建设 2026/4/7 21:26:11

DSP 28377 锁相环代码

dsp 28377 锁相环代码半夜调试电机控制板的时候&#xff0c;最怕遇到时钟信号飘得亲妈都不认识。DSP 28377这货的锁相环配置说难不难&#xff0c;但手册里那些寄存器名字看得人眼晕。今天咱们直接扒开TI官方例程的裤衩&#xff0c;看看PLL到底怎么驯服。先甩个祖传配置函数镇楼…

作者头像 李华
网站建设 2026/4/15 14:50:13

【上海理工大学】VC试题集合[2025-12-08]

【上海理工大学】VC试题集合[2025-12-08] 规则 时间&#xff1a;12月1日1月5日&#xff0c;1月5日&#xff08;周一上午第35节&#xff09;上交程序&#xff0c;提交的方式可以发送邮件&#xff08;ghanmingvip.sina&#xff09;&#xff0c;注明成员名称及学号。提供报告&am…

作者头像 李华