• 环形石子合并——区间DP


    将 nn 堆石子绕圆形操场排放,现要将石子有序地合并成一堆。

    规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分。

    请编写一个程序,读入堆数 nn 及每堆的石子数,并进行如下计算:

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

    输入格式

    第一行包含整数 n,表示共有 n 堆石子。

    第二行包含 n 个整数,分别表示每堆石子的数量。

    输出格式

    输出共两行:

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

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

    数据范围

    1≤n≤200

    输入样例:

    1. 4
    2. 4 5 9 4

    输出样例:

    1. 43
    2. 54

    思路:

    f[i][j]:左端点为i,右端点为j的区间已经合并,属性:区间的得分

    一个大的区间的得分=两个小的区间的得分+这个大区间内的所有石子数

    何为环形区间?就只是区间内的第一个数和最后一个数是相邻的。

    怎么解决环形问题?输入的时候数组开两倍,在n+1这个位置开始往后重新输入一遍

    code:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. int n;
    6. int a[410];
    7. int s[410];
    8. int f[410][410]; //f[i][j]:左端点为i,右端点为j这个区间已经合并完毕的得分 max
    9. int g[410][410]; //属性:min
    10. int main()
    11. {
    12. memset(g,0x3f,sizeof g);
    13. cin>>n;
    14. for(int i=1;i<=n;i++)
    15. {
    16. cin>>a[i];
    17. a[i+n] = a[i];
    18. g[i][i] = g[i+n][i+n] = 0;
    19. }
    20. for(int i=1;i<=2*n;i++) s[i] = s[i-1]+a[i];
    21. for(int len=2;len<=n;len++)
    22. for(int i=1;i+len-1<2*n;i++)
    23. {
    24. int j = i+len-1;
    25. for(int k=i;k
    26. {
    27. f[i][j] = max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
    28. g[i][j] = min(g[i][j],g[i][k]+g[k+1][j]+s[j]-s[i-1]);
    29. }
    30. }
    31. int maxn = -0x3f3f3f3f;
    32. int minn = 0x3f3f3f3f;
    33. for(int i=1;i<=n+1;i++)
    34. {
    35. maxn = max(maxn,f[i][i+n-1]);
    36. minn = min(minn,g[i][i+n-1]);
    37. }
    38. cout<
    39. cout<
    40. return 0;
    41. }

  • 相关阅读:
    (c语言)用冒泡排序模拟实现qsort()函数交换整数
    循环队列的实现
    Electron:菜单
    java计算机毕业设计健身俱乐部管理系统MyBatis+系统+LW文档+源码+调试部署
    记-doris-学习笔记
    2022-01-27-JavaScript
    [计算机提升] Windows系统权限
    华为云云耀云服务器L实例评测|部署功能强大的开源物联平台ThingsBoard
    Rust开发——闭包使用示例
    python 去除HTML中的空标签对
  • 原文地址:https://blog.csdn.net/m0_56511205/article/details/127845244