专栏文章
题解:P1775 石子合并(弱化版)
P1775题解参与者 3已保存评论 4
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @mio7tiul
- 此快照首次捕获于
- 2025/12/02 14:46 3 个月前
- 此快照最后确认于
- 2025/12/02 14:46 3 个月前
题意
有 个质量为 的石子,合并相邻的两堆代价为两堆石子的质量之和,求最小代价。
思路
一道区间 DP 的水题。
- 状态定义: 表示从第 堆到第 堆合并成一堆的最小代价。
- 初始化 DP 数组:因为我们要求最小值,所以需要将 DP 数组初始为极大值。显然,每一堆合并成自己的代价为 ,所以 。
- 状态转移:由第 堆到第 堆的合并成一堆后这一堆的质量肯定是 ,那么我们知道了第 堆合并到第 堆的最小代价为 ,再枚举一个 ,很明显 加上 再加上新的代价,也就是从第 堆到第 堆合并成一堆的大小加第 堆到第 堆合并成一堆的大小。综上可以得到 这个状态转移方程
- 优化:这里的 不难让我们想到前缀和,于是 就是最终状态转移方程。
- 具体实现:用三重循环枚举,第一重枚举合并段的长度 ,第二重枚举合并段的起始位置 ,并且可以确定结束位置 为 ,第三重循环枚举 ,以确定 的值。具体细节见代码。
代码
CPP#include <bits/stdc++.h>
#define code using
#define from namespace
#define Yxa_Sheep std
code from Yxa_Sheep;
int n, a[310], sum[310], f[310][310];
int main()
{
scanf("%d", &n), memset(f, 0x3f, sizeof f);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i], f[i][i] = 0;
for (int len = 2; len <= n; len++)
for (int i = 1; i + len - 1 <= n; i++)
{
int j = i + len - 1;
for (int k = i; k < j; k++)
f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + sum[j] - sum[i - 1]);
}
printf("%d", f[1][n]);
return 0;
}
做完此题的可以去这里:P1880 [NOI1995] 石子合并。
题解来之不易,且看且珍惜。点个赞再走吧。
相关推荐
评论
共 4 条评论,欢迎与作者交流。
正在加载评论...