• 石子合并 区间dp模板


    题意:中文题

    Description

    在操场上沿一直线排列着 n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分。允许在第一次合并前对调一次相邻两堆石子的次序。

    计算在上述条件下将n堆石子合并成一堆的最小得分。

    Input

    输入数据共有二行,其中,第1行是石子堆数n≤100;
    第2行是顺序排列的各堆石子数(≤20),每两个数之间用空格分隔。

    Output

    输出合并的最小得分。

    Sample Input

    3 2 5 1

    Sample Output

    11

    Source

    NOI1995

     
    题解:区间dp,交换的处理
     
     
    代码
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
    #define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
    #define mmm(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    #define mp make_pair;
    const int maxn=1e2+5;
    int n;
    int a[maxn];
    int dp[maxn][maxn];
    int main() {
        cin >> n;
        //fill(dp, dp + maxn*maxn, 1e9);
        int ans = 1e9;
        rep(i, 1, n)cin >> a[i], dp[i][i] = 0;
        rep(i, 1, n-1) {
            swap(a[i], a[i + 1]);
            rep(len, 2, n)//len
                rep(i, 1, n - len + 1)//begin
            {
                dp[i][i + len - 1] = 1e9;
                int sum = 0; rep(j, i, i + len - 1)sum += a[j];
                rep(k, i, len + i - 2)//k
                {
                    dp[i][i + len - 1] = min(dp[i][i + len - 1], dp[i][k] + dp[k + 1][i + len - 1] + sum);
                }
            }
            ans=min(ans,dp[1][n]);
            swap(a[i], a[i + 1]);
        }
        cout << ans;
        cin >> n;
    }
    成功的路并不拥挤,因为大部分人都在颓(笑)
  • 相关阅读:
    cookie和session详解
    MacOS Sierra10.12.4编译Android7.1.1源代码必须跳的坑
    LeetCode——4Sum &amp; 总结
    C#深拷贝
    iOS9中怎样注冊远程通知
    hdu1542 Atlantis (线段树+扫描线+离散化)
    HTML杂记
    OpenCV中图像算术操作与逻辑操作
    java集群优化——ORM框架查询优化原理
    RVM切换ruby版本号
  • 原文地址:https://www.cnblogs.com/SuuT/p/9095294.html
Copyright © 2020-2023  润新知