石子合并(区间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<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#include<cmath>
#define Inf 0x3f3f3f3f
const int maxn=1e5+5;
typedef long long ll;
using namespace std;
int a[205],g[205][205],sum[205];
int dp[205][205];
int main()
{
   int n;
   cin>>n;
   
   for(int t=1;t<=n;t++)
   {
       scanf("%d",&a[t]);
   }
   for(int t=1;t<=n;t++)
   {
       sum[t]=sum[t-1]+a[t]; 
   }
   memset(dp,Inf,sizeof(dp));
   for(int t=1;t<=n;t++)
   {
       for(int j=t;j<=n;j++)
       {
           g[t][j]=sum[j]-sum[t-1];
    }
   }
   for(int t=1;t<=n;t++)
   {
       dp[t][t]=0;
   }
   for(int l=1;l<n;l++)
   {
       for(int j=1;j+l<=n;j++)
       {
           int r=j+l;
           for(int k=j;k<r;k++)
           {
               dp[j][r]=min(dp[j][r],dp[j][k]+dp[k+1][r]+g[j][k]+g[k+1][r]); 
        }
    }
   }
   cout<<dp[1][n]<<endl;
   return 0;
}
原文地址:https://www.cnblogs.com/Staceyacm/p/11228382.html