石子归并问题

来源:互联网 发布:淘宝店更换类目影响 编辑:程序博客网 时间:2024/06/18 06:15

石子归并问题

问题引用

题目链接点这—>石子归并

N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。 Input第1行:N(2 <= N <= 100) 第2 - N + 1:N堆石子的数量(1 <= Ai <= 10000)Output输出最小合并代价

思路

假设dp[i][j]为区间[i,j]的最小代价,n为最大石子数,sum[i][j]为区间[i,j]的和。想要求的[1,n]的最小代价,让我想到了枚举,设断点k( k = 1,2,3...n-1) dp[1][n] = min (dp[1][n],dp[1][k] + dp[k+1][n] + sum[1][n])。dp[1][k]和dp[k+1][n]是求所付出[1,k],[k+1,n]的最小代价,而sum[i][j]是合成[1,k][k+1,n]两个石堆的新代价加起来就是我们求的区间[1,n]的代价。由于k我们枚举为[1,k-1]所以求出来的代价是最小代价。那么dp[1][k]和dp[k+1][n]怎么求? 和上诉步骤一样。

代码

#include <iostream>#include <algorithm>using namespace std;const int INF = 1e8;const int N = 200;long long dp[N][N], sum[N] = {0}, num[N];int main() {    int n;    cin >> n;    for (int i = 1; i <= n; i++) {        cin >> num[i];        sum[i] = sum[i-1] + num[i];        //只有一堆则合成代价为0        dp[i][i] = 0;    }    // 状态长度    for (int len = 2; len <= n; len++) {        // i 为起点, j 为终点        for (int i = 1; i + len - 1 <= n; i++) {            int j = i + len - 1;            dp[i][j] = INF;            for (int k = i; k < j; k++)                // 当前合并代价加上之前合并代价                dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]);        }    }    cout << dp[1][n] << endl;    return 0;}
原创粉丝点击