The universe said |

Momo·Trace

园龄:3年3个月粉丝:6关注:1

石子合并(弱化版)

石子合并(弱化版)

题目描述

设有 N(N300) 堆石子排成一排,其编号为 1,2,3,,N。每堆石子有一定的质量 mi(mi1000)。现在要将这 N 堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻。合并时由于选择的顺序不同,合并的总代价也不相同。试找出一种合理的方法,使总的代价最小,并输出最小代价。

输入格式

第一行,一个整数 N

第二行,N 个整数 mi

输出格式

输出文件仅一个整数,也就是最小代价。

样例

样例输入 #1

4
2 5 3 1

样例输出 #1

22

解析

dp[i][j]表示区间[i,j]的最小价值。

不妨从终点考虑问题,即结果为两个子区间合并的最小值再加上合并需要的代价即可。

枚举两个子区间,即枚举这个区间的中间点k,使这个区间被分为[i,k][k+1,j]两个区间,取一遍最小值加上合并的即为当前区间所求。

至于合并的代价,用前缀和即可。

所以dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]sum[i1])

代码

#include<bits/stdc++.h>
using namespace std;
int dp[310][310],a[310],sum[310];
int main()
{
int n;
cin>>n;
memset(dp,0x3f,sizeof(dp));//初始化1,因为是求最小代价,所以初始化设为很大的一个数,为了后面更新。
for(int i=1;i<=n;i++)
{
cin >> a[i];
sum[i]=sum[i-1]+a[i];
dp[i][i]=0;//初始化2,他自己本身的代价为0。
}
for(int len=2;len<=n;len++)
{
for(int i=1;i<=n-len+1;i++)
{
int j=i+len-1;
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]);
}
}
}
cout<<dp[1][n];
}
posted @   Momo·Trace  阅读(94)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示