码迷,mamicode.com
首页 > 其他好文 > 详细

区间DP——石子合并问题

时间:2015-03-17 19:58:49      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

述    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。

 
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
13 7 8 16 21 4 18
大意:如题意:用一个k记录从是第几次,然后i从1开始到n-k-1结束,j=i+l-1表示,插入m,所以要sum[j]-sum[i-1]
O(n^3)代码
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 1000;
const int inf = 9999999;
int dp[MAX][MAX],ans[MAX],sum[MAX];
int main()
{
    int n;
    scanf("%d",&n);
    memset(dp,0,sizeof(dp));
    sum[0] = 0;
    for(int i = 1; i <= n ; i++){
        scanf("%d",&ans[i]);
        sum[i] = sum[i-1] + ans[i];
    }
    int k,i,j;
    for(int k = 2; k <= n ; k++){
        for(int i = 1; i <= n - k + 1;i++){
            j = i + k - 1;
           dp[i][j] = inf;
           for(int m = i; m < j ; m++){
                dp[i][j] = min(dp[i][j],dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1]);
           }
        }
    }
   printf("%d\n",dp[1][n]);
  return 0;
}
View Code

可以用平行四边形优化,即用一个数组s来存储每个最优位置。

技术分享
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAX = 1000;
    const int inf = 9999999;
    int dp[MAX][MAX],ans[MAX],sum[MAX],s[MAX][MAX];
    int main()
    {
        int n;
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        sum[0] = 0;
        for(int i = 1; i <= n ; i++){
            scanf("%d",&ans[i]);
            sum[i] = sum[i-1] + ans[i];
            s[i][i] = i;
        }
        int k,i,j;
        for(int k = 2; k <= n ; k++){
            for(int i = 1; i <= n - k + 1;i++){
                j = i + k - 1;
               dp[i][j] = inf;
               for(int m = s[i][j-1]; m <= s[i+1][j];m++){
                   if(dp[i][j] > dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1]){
                       dp[i][j] = dp[i][m]+dp[m+1][j]+sum[j]-sum[i-1];
                       s[i][j] = m;
                 }
               }
            }
        }
       printf("%d\n",dp[1][n]);
      return 0;
    }
View Code

 

区间DP——石子合并问题

标签:

原文地址:http://www.cnblogs.com/zero-begin/p/4345143.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!