• 算法提高 合并石子【动态规划】


    问题描述
      在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。
    输入格式
      输入第一行包含一个整数n,表示石子的堆数。
      接下来一行,包含n个整数,按顺序给出每堆石子的大小 。
    输出格式
      输出一个整数,表示合并的最小花费。
    样例输入
    5
    1 2 3 4 5
    样例输出
    33
    数据规模和约定
      1<=n<=1000, 每堆石子至少1颗,最多10000颗。
    题目分析
      这是一道很经典的动态规划题(据说),但是我不会,哈哈哈。我的理解是,逆向考虑这个题,把一堆石头分为两堆。
      因此,设置一个中间点k ,d[ i ][ j ] = min(d[ i ][ n ], d[ 1 ][ k ] + d[k + 1][ j ]),遍历每一个处于[ i , j ]中的每一个中间点k
     
    递归实现的话,最后一个样例会超时。
    int dp(int i, int j) {
        if (d[i][j] || i==j)    return d[i][j];
        int mi = bigdata;
        for (int ii = i; ii < j; ii++) {
            int t = dp(i, ii) + dp(ii + 1, j);
            if(mi > t)    mi = t;
        }
        return d[i][j] = mi + sum[j] - sum[i - 1];
    }

    循环实现

    for (int i = n - 1; i > 0; i--) {//起点
            for (int j = i + 1; j <= n; j++) {//终点
                long long t = bigdata;
                for (int k = i; k < j; k++) {//中间点
                    long long  temp = d[i][k] + d[k + 1][j];
                    if (t > temp)    t = temp;
                }
                d[i][j] = t + sum[j] - sum[i - 1];
            }
        }
  • 相关阅读:
    SQL 语法总结
    终于开始用github了
    前端开发第一阶段总结
    windows系统快捷操作の高级篇
    windows系统快捷操作の进阶篇
    windows系统快捷操作の基础篇
    安装使用ubuntu问题汇总
    十进制转任意进制
    任意进制转10进制
    爬取妹子图(requests + BeautifulSoup)
  • 原文地址:https://www.cnblogs.com/woxiaosade/p/10455677.html
Copyright © 2020-2023  润新知