石子合并
c++
石子合并
/* 问题描述: 设有 N 堆石子排成一排,其编号为 1,2,3,…,N。 每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N 堆石子合并成为一堆。 每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同。 例如有 4 堆石子分别为 1 3 5 2, 我们可以先合并 1、2 堆,代价为 4,得到 4 5 2, 又合并 1,2 堆,代价为 9,得到 9 2 ,再合并得到 11,总代价为 4+9+11=24; 如果第二步是先合并 2,3 堆,则代价为 7,得到 4 7,最后一次合并代价为 11,总代价为 4+7+11=22。 问题是:找出一种合理的方法,使总的代价最小,输出最小代价。 输入格式 第一行一个数 N 表示石子的堆数 N。 第二行 N 个数,表示每堆石子的质量(均不超过 1000)。 数据范围 1 ≤ N ≤ 300 解题思路: f[len][i] 表示 将 (i, i + len - 1) 范围的石子合并成一堆,所需要的最小代价 f[len][i] = min(f[k][i] + f[len - k][i + k] + sum(i..i+len-1), 1<=k<=len-1) 注意点: len = 1时候,初始化为 0 复杂度: O(N^2) */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N = 310; int f[N][N], sum[N]; int n, a[N]; int solution_one() { sum[0] = 0; for (int i = 1; i <= n; i ++ ) { sum[i] = sum[i - 1] + a[i]; } memset(f, 0x3f, sizeof f); for (int i = 1; i <= n; i ++ ) { f[1][i] = 0; } int j; for (int len = 2; len <= n; len ++ ) { for (int i = 1; i + len - 1 <= n; i ++ ) { j = i + len - 1; for (int k = i + 1; k <= j; k ++ ) { f[len][i] = min(f[len][i], f[k - i][i] + f[j - k + 1][k] + sum[j] - sum[i - 1]); } } } return f[n][1]; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i ++ ) { scanf("%d", &a[i]); } int res = solution_one(); printf("%d\n", res); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)