题意:有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
题解:使用区间dp,用dp[i][j]来表示合并第i堆到第j堆石子的最小代价,状态转移方程为dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+w[i][j]),其中w[i][j]表示把两部分合并起来的代价,即从第i堆到第j堆石子个数的和,为了方便查询,可以用sum[i]表示从第1堆到第i堆的石子个数和,那么w[i][j]=sum[j]-sum[i-1].
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=205;
int n,x;
int sum[maxn];
int dp[maxn][maxn];
int main()
{
while(~scanf("%d",&n)){
sum[0]=0;
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%d",&x);
sum[i]=sum[i-1]+x;
dp[i][i]=0;
}
for(int len=2;len<=n;len++){
for(int i=1;i<=n;i++){
int j=i+len-1;
if(j>n){
continue;
}
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]);
}
}
}
printf("%d\n",dp[1][n]);
}
return 0;
}