题意:给n堆石子,按照顺序排列,只能相邻两堆石子合并,求最后合并为一堆时所花费的最小代价,石子合并代价为两堆石子之和。
输入:
n(石子堆数)
Xi(每堆石子个数)
输出:
T(最小代价)
思路:经典石子归并问题,区间DP,原谅我对DP并不怎么感冒,简单点来说,首先预处理记下i到j的石子总数,用数组存放,然后在DP的过程中,因为求解的是最小代价,我们可以这样想,先找出两堆石子所有情况中最小的,然后再这个基础上依次转移到三堆,四堆,直到n堆,所以复杂度n^3,在每堆情况里面,状态转移方程为
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]);这里i-k是一堆,(k+1)-j是一堆,然后要加上这两堆的花费之和,所以递归求解就可以得到1-n堆石子最小代价花费了。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define M 101
#define MAX 10000000
int n,dp[M][M],sum[M][M],s[M];
int main()
{
int i,j,k;
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(i=1; i<=n; i++)
{
scanf("%d",&s[i]);
sum[i][i]=s[i];
for(j=i+1; j<=n; j++)
sum[i][j]=sum[i][j-1]+s[j];
}
for(int k=2; k<=n; k++)
{
for(i=1; i<=n-k+1; i++)
{
j=i+k-1;
dp[i][j]=MAX;
for(k=i; k<=j-1; k++)
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]);
}
}
printf("%d\n",dp[1][n]);
return 0;
}