zoukankan      html  css  js  c++  java
  • 区间DP——石子合并

    状态表示的时候表示的是某一段区间。

    动态规划:

    1、状态表示:f[i, j] 第i堆到第j堆的区间

    1)集合:所有将第i堆和第j堆石子合并成一堆石子的 合并方法的集合

    2)min: 所有合并方式代价的最小值

    2、状态计算:f[1][n]就是所求的,从第1堆一直合并到第n堆的合并方式的最小值。

    最后一定是将两堆合并成一堆,将最后一次合并作为分界线。

    PS:所有的减去一个数加上一个数并不会影响最大值和最小值是谁。

    [i, k], [k + 1, j]把这最后一步去掉,然后求最小值:f[i, k] + f[k + 1, j] + s[j] - s[i - 1]

    然后f[i, j] = Min{f[i, k] + f[k + 1,j] + s[j] - s[i - 1]}, k = i ~ j - 1

    时间复杂度:状态两维 O(n^2 * k) = O(n^2 * n) = O(n ^ 3) = 2.7 * 10^7

    输入样例:

    4
    1 3 5 2
    

    输出样例:

    22
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 301;
    
    int f[N][N], s[N];
    
    int main()
    {
        int n;
        cin>>n;
        for(int i = 1;i <= n;i++) cin>>s[i];
        
        for(int i = 1;i <= n;i++) s[i] += s[i-1];
        
        for(int len = 2;len <= n;len++)
            for(int i = 1; i + len - 1 <= n;i++)
            {
                int l = i, r = i + len - 1;
                f[l][r] = 1e9;
                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;
    }
  • 相关阅读:
    Shortest Paths
    Minimum Spanning Trees
    Programming Assignment 1: WordNet
    Directed Graphs
    内连接
    数据中台文档--参考
    ORACLE触发器字段触发
    DTS
    oracle删除归档日志
    OGG 分区表
  • 原文地址:https://www.cnblogs.com/longxue1991/p/12751200.html
Copyright © 2011-2022 走看看