zoukankan      html  css  js  c++  java
  • ACwing 282

    设有N堆石子排成一排,其编号为1,2,3,…,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
    

    题目大意:

    输入一个n,接下来输入 n 个数,ai 表示合并第 i 个石子的质量,你需要将这些石子合并成一堆,每次只能选择相邻的两堆进行合并,合并的代价是两堆石子质量之和,你需要找出一种方式使得合并完的代价最小,并输出这个代价。

    解题思路:

    经典区间dp问题,从两方面分析这个问题:

    • 状态表示: 用两维去表示状态,区间问题一般都可以这样表示,f(i, j) 表示从第 i 堆石子合并到第 j 堆石子所需代价,而这道题的属性是最小值,所以用f(i, j) 表示从第 i 堆合并到第 j 堆的最小代价。
    • 状态计算: 看看如何划分这个集合,f[i][j] 可以从什么状态转移过来呢,第一重循环可以枚举长度len,从1 -> n 第二重枚举一个起点,i到i + len - 1 ,考虑最后一次合并,他一定是将两堆石子合并成一堆,所以第三重循环可以枚举分割点k ,所以每次合并的代价一定是max(f[l][r], f[l][k] + f[k + 1][r] + (sum[r] - sum[l - 1])) sum为前缀和数组,因为这次合并的代价要加上l - r 的总和,维护一个前缀和可以O1 时间去得到sum[l, r], k 的范围是i -> j - 1 ,因为至少要有一堆,以k为分界点,最后输出f(1, n) 即可。

    Code:

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const int N = 310;
    
    int n;
    int s[N]; 
    int f[N][N];
    
    int main()
    {
        cin >> n;
        
        for (int i = 1; i <= n; i ++)
        {
            int x;
            cin >> x;
            s[i] = s[i - 1] + x;//维护一个前缀和
        }
        
        for (int len = 2; len <= n; len ++)//长度是1的代价一定是0,所以不必从1开始枚举
            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;
    }
    
  • 相关阅读:
    Javascript实现图片的预加载的完整实现
    python模块查找机制探究
    网络协议模拟之QQ微博分享接口应用
    每周一荐:差异利器Beyond Compare
    Asp.Net MVC4 入门介绍
    单元测试一例:学习断言、测试用例函数的编写
    开源一个网络框架
    .NET服务端持续输出信息到客户端
    Python服务器改造
    CYQ.Data 数据框架 V4.0
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294129.html
Copyright © 2011-2022 走看看