ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NC50493 石子合并

2022-08-15 04:00:25  阅读:188  来源: 互联网

标签:得分 int sum 石子 合并 NC50493 dp


题目链接

题目

题目描述

将n堆石子绕圆形操场排放,现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分。
请编写一个程序,读入堆数n及每堆的石子数,并进行如下计算:

  1. ​ 选择一种合并石子的方案,使得做n-1次合并得分总和最大。
  2. ​ 选择一种合并石子的方案,使得做n-1次合并得分总和最小。

输入描述

输入第一行一个整数n,表示有n堆石子。
第二行n个整数,表示每堆石子的数量。

输出描述

第一行为合并得分总和最小值,
第二行为合并得分总和最大值。

示例1

输入

4
4 5 9 4

输出

43
54

备注

对于\(100 \%\) 的数据,有 \(1 \leq n \leq 200\) 。

题解

知识点:区间dp。

普通的石子合并用区间dp直接能做,但这里是环形的,有两种处理方式,比较简单的是复制一段接在后面,就可以做了。

如果是线性dp的环形处理可以做两次dp,一次是强制断开的情况,一次是强制链接的情况。

可以用前缀和优化求和。

时间复杂度 \(O(n^3)\)

空间复杂度 \(O(n^2)\)

代码

#include <bits/stdc++.h>

using namespace std;

int sum[407], dp[407][407];///循环,端点开大一倍

int main() { 
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) cin >> sum[i], sum[i + n] = sum[i];
    for (int i = 1;i <= 2 * n;i++) sum[i] += sum[i - 1];

    memset(dp, 0x3f, sizeof(dp));
    for (int i = 1;i <= 2 * n;i++) dp[i][i] = 0;
    for (int l = 2;l <= n;l++) {///算到长度为n
        for (int i = 1;i <= 2 * n;i++) {///搞循环,因为分割区间可能到加长的区间,因此大于n的区间也要算
            int j = i + l - 1;
            for (int k = i;k < j;k++)
                dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);
        }
    }
    int ans = ~(1 << 31);
    for (int i = 1;i <= n;i++) ans = min(ans, dp[i][i + n - 1]);
    cout << ans << '\n';

    memset(dp, 0, sizeof(dp));
    for (int l = 2;l <= n;l++) {
        for (int i = 1;i <= 2 * n;i++) {///搞循环
            int j = i + l - 1;
            for (int k = i;k < j;k++)
                dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);
        }
    }
    ans = 0;
    for (int i = 1;i <= n;i++) ans = max(ans, dp[i][i + n - 1]);
    cout << ans << '\n';
    return 0;
}

标签:得分,int,sum,石子,合并,NC50493,dp
来源: https://www.cnblogs.com/BlankYang/p/16586913.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有