题目链接
题意:给你n个石子 每次可以合并相邻的两个石子 消耗为两个石子的和 求最小的消耗
思路 :
dp[i][j] 表示重i到j的合并的最小权值和
sum[i][j] 表示 i到j的和
pre[i]表示1到i的前缀和
每次先将所有的2个石子合并 然后是3个石子合并(等价于2个石子加上1个石子的合并)依次类推4个,5个到n个
转移方程 dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+sum[i][j])
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 1005;
const int inf = 0x3f3f3f3f;
int a[MAXN];
int dp[MAXN][MAXN];
int sum[MAXN][MAXN];
int pre[MAXN];
int main()
{
int n;
scanf("%d", &n);
for(int i=1; i<=n; ++i)
{
scanf("%d", &a[i]);
pre[i]=pre[i-1]+a[i];
}
for(int i=1; i<=n; ++i)
{
for(int j=i+1; j<=n; ++j)
{
sum[i][j]=pre[j]-pre[i-1];
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n-i;++j)
{
dp[j][j+i]=inf;
for(int k=j; k<=j+i;++k)
{
dp[j][j+i]=min(dp[j][j+i], dp[j][k]+dp[k+1][j+i]+sum[j][j+i]);
}
}
}
printf("%d\n", dp[1][n]);
return 0;
}