• Acwing 282. 石子合并 区间dp


    地址 https://www.acwing.com/problem/content/284/

    设有N堆石子排成一排,其编号为1,23,…,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
    输入样例:
    4
    1 3 5 2
    输出样例:
    22

    解答

    首先是暴力遍历思想.尝试各种合并方式,显然不是TLE 就是MLE。

    但是在暴力遍历的过程中可以发现这么一个规律

    1~n的石子合并操作中  如果最后合并的点是k

    最后一次的合并的成本总和是 

     dp[1][n] = max(dp[1][2]+dp[2][n] + 1~n之间的所有石子的总和成本  ,   dp[1][3]+dp[4][n] + 1~n之间的所有石子的总和成本,     dp[1][3]+dp[4][n] + 1~n之间的所有石子的总和成本 ........ );

    推导出下式  

     dp[1][n] = max(dp[1][k]+dp[k+1][n] + 1~n之间的所有石子的总和成本 );  ( 1<=k <= n)

    同样式子中的1~k  k+1~n 也可以看做一段距离的石子合并 且并不互相影响,那么可以使用递归逐步缩小问题规模来解决掉这个问题

    #include <iostream>
    
    
    using namespace std;
    
    const int N = 310;
    
    int arr[N];
    int dp[N][N];
    int n;
    
    
    int main()
    {
        cin >> n;
        
        for(int i = 1;i <=n;i++){
            cin >> arr[i];
        }
        
        for(int i =1;i <=n;i++){
            arr[i] += arr[i-1];
        }
        //从长度为2的石子合并开始计算 为后面的3 4 5长度DP计算好需要的dp数组
        for(int len =2;len <=n;len++){
            for(int i =1;i+len-1<=n;i++){
                int j= i+len-1;
                dp[i][j] = 1e9;
                for(int k = i-1; k<=j-2;k++){
                    dp[i][j]= min(dp[i][j],dp[i][k+1]+dp[k+2][j]+arr[j]-arr[i-1])  ;
                }
            }
        }
        
        cout << dp[1][n] <<endl;
        
        
        return 0;
    }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    insert 语句后面的一些参数使用知识
    mysql通信协议的半双工机制理解
    整理超级全局变量与全局变量的知识
    php获取输入流
    插入数据sql使用“insert into set”形式的理解
    《LINUX与UNIX SHELL编程指南》学习笔记
    转载别人空间的一篇好文技术没有转换成生产力
    C# 查找打开的窗口
    sql:inner join,left join,right join,full join的用法及含义
    pc doctor启动到进度条的时候自动退出
  • 原文地址:https://www.cnblogs.com/itdef/p/13591354.html
Copyright © 2020-2023  润新知