AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 282. 石子合并    原题链接    简单

作者: 作者的头像   Mellina ,  2023-01-15 14:51:13 ,  所有人可见 ,  阅读 179


1


$\LARGE\color{orange}{刷题日记(算法提高课)}$

这是一道典型的区间 DP 问题

我们定义 $f[l][r]$ 表示集合:合并区间 $[l,r]$ 内的所有石子的不同选法,属性为最大值

对于区间 DP 问题,我们先枚举区间长度,后枚举区间左端点

对于同一个区间的所有不同选法而言,我们将区间 $[l,r]$ 分成 $[l,k]$ 和 $[k+1,r]$ 通过枚举 $k$ 来实现对 $f[l][r]$ 进行赋值

这么考虑是因为,这个区间最后一步一定是两个石子进行合并,而这两个石子所需体力各不相同,而导致这一点的正是对这段区间不同的划分,因此我们通过枚举 $k$ 来实现对区间的划分

因此状态转移方程为:

$$ f[l][r]=max(f[l][r],\ f[l][k]+f[k+1][r]+s[l-1][r])\ ,\ 其中 s[i] 为前缀和数组 $$

完整代码:

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 310;
int s[N];
int f[N][N];
int n;

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> s[i];
    for(int i = 1; i <= n; i++)
        s[i] += s[i - 1];

    for(int len = 2; len <= n; len++)//枚举区间长度
        for(int i = 1; i + len - 1 <= n; i++)//枚举左端点
        {
            int l = i, r = i + len - 1;
            f[l][r] = 0x3f3f3f3f;
            for(int k = l; k < r; k++)
                f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + s[r] - s[l - 1]);
        }

    cout << f[1][n] << endl;

    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息