合并石子 区间dp水题

合并石子 

链接: nyoj 737

描述: 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
tags:最基本的区间dp,这题范围小,如果n大一些,还是要加个平行四边行优化。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
typedef  long long   ll;
#define  rep(i,a,b)  for(int i=a; i<=b; ++i)
#define  inf  1e18
const int N=1005;

int n, a[N];
ll  dp[N][N], f[N][N], sum[N][N], sum1[N];
int main()
{
    while(scanf("%d", &n)!=EOF) 
    {
        rep(i,1,N-1) rep(j,i,N-1) dp[i][j]=inf;
        rep(i,1,n)  scanf("%d", &a[i]), sum1[i]=sum1[i-1]+a[i];
        rep(i,1,n) rep(j,i+1,n) {
            sum[i][j]=sum1[j]-sum1[i-1];
        }
        rep(i,1,n) f[i][i]=i, dp[i][i]=0;
        rep(len, 2, n)  
            for(int i=1; i+len-1<=n; ++i)
        {
            int j=i+len-1;
            for(int k=f[i][j-1]; k<=f[i+1][j]; ++k)
            {    
                if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[i][j]) {
                    dp[i][j]= dp[i][k]+dp[k+1][j]+sum[i][j];
                    f[i][j]=k;
                }
            }    
        }
        printf("%lld\n", dp[1][n]);
    }
    
    
    return 0;
}
posted @ 2017-07-08 21:03  v9fly  阅读(165)  评论(0编辑  收藏  举报