zoukankan      html  css  js  c++  java
  • SDNU 1048.石子合并2(区间dp)

    Description

    有n堆石子排成一圈,每次选择相邻的两堆石子,将其合并为一堆,记录该次合并的得分为两堆石子个数之和。已知每堆石子的石子个数,求当所有石子合并为一堆时,最小的总得分。

    Input

    第一行一个整数n(1 <= n <= 200),表示石子堆数; 第二行n个整数a(1 <= a <= 100),表示每堆石子的个数,这些石子首尾相接排成一圈。

    Output

    一个整数,表示最小总得分。

    Sample Input

    5
    7 6 5 7 100

    Sample Output

    175

    Source

    Unknown
    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define eps 1e-9
    #define pi acos(-1)
    
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9+7;
    const int maxn = 1000 + 8;
    
    int n, a[maxn], sum[maxn], dp[maxn][maxn], mi;
    
    int main()
    {
        std::ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        cin >> n;
        sum[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            cin >> a[i];
            sum[i] += a[i] + sum[i - 1];
        }
        for(int len = 1; len <= n; len++)
        {
            for(int i = 1; i <= n; i++)
            {
                int en = (i + len) % n == 0 ? n : (i + len) % n;
                int tmp;
                if(i + len <= n)
                    tmp = sum[i + len] - sum[i - 1];
                else
                    tmp = sum[n] - sum[i - 1] + sum[(i + len) % n];
                dp[i][en] = inf;
                for(int k = 0; k < len; k++)
                    dp[i][en] = min(dp[i][en], dp[i][(i + k) % n == 0 ? n : (i + k) % n] + dp[(i + k + 1) % n == 0 ? n : (i + k + 1) % n][en] + tmp);
            }
        }
        mi = dp[1][n];
        for(int i = 2; i <= n; i++)
            if(mi > dp[i][i - 1])
                mi = dp[i][i - 1];
        cout << mi <<'
    ';
        return 0;
    }
  • 相关阅读:
    《时间的朋友》2017跨年演讲:观后感
    如何实现目标?
    不患贫而患不均
    科学地定目标(附我的目标)
    书单:我的“基本书”
    你只有非常努力,才能看起来毫不费力
    买书?买知识?
    论知识与技能
    【读书笔记】《代码不朽》
    【工作实践】如何创新?
  • 原文地址:https://www.cnblogs.com/RootVount/p/11480394.html
Copyright © 2011-2022 走看看