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

nyoj 石子归并(1)

时间:2014-08-17 17:09:13      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:acm   dp   

石子合并(一)

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述
    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
7
13 7 8 16 21 4 18
样例输出
9
239
来源
经典问题
上传者
TC_胡仁东
思路:区间dp~dp[i][j]表示从i到j的范围内合并成一堆最小的耗费~
          状态转移方程: dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
 这道题和括号匹配是一样的思路~~朴素dp O(n^3)的复杂度
PS:(1)有一种四边形优化的方案~
        (2)有另外一种变形~就是环形合并
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <cmath>
const int maxn=220;
using namespace std;
int dp[maxn][maxn];
int sum[maxn];
int main()
{
 int n;
 while(cin>>n)
 {
  for(int i=1;i<=n;i++)
   {
     cin>>sum[i];
     sum[i]+=sum[i-1];
   }
  for(int i=0;i<=n;i++)
    dp[i][i]=0;
  for(int k=1;k<n;k++)
  {
   for(int i=1;i<=n-k;i++)
    {
        dp[i][i+k]=99999999;
        for(int j=i;j<i+k;j++)
          if(dp[i][i+k]>dp[i][j]+dp[j+1][i+k]+sum[i+k]-sum[i-1])
             dp[i][i+k]=dp[i][j]+dp[j+1][i+k]+sum[i+k]-sum[i-1];
    }
  }
  cout<<dp[1][n]<<endl;
 }
 return 0;
}


nyoj 石子归并(1),布布扣,bubuko.com

nyoj 石子归并(1)

标签:acm   dp   

原文地址:http://blog.csdn.net/liusuangeng/article/details/38639079

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