SSLOJ2863石子合并

   日期:2020-08-21     浏览:94    评论:0    
核心提示:Description在一个操场上一排地摆放着N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请设计一个程序,计算出将N堆石子合并成一堆的最小得分。Input每组数据第1行为一个正整数N(2<=N<=100),以下N行,每行一个正整数,小于10000,分别表示第i堆石子的个数(1<=i<=N)。Output对于每组数据输出一个正整数,即最小得分Sample Input713781621

Description

在一个操场上一排地摆放着N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请设计一个程序,计算出将N堆石子合并成一堆的最小得分。

Input

每组数据第1行为一个正整数N(2<=N<=100),以下N行,每行一个正整数,小于10000,分别表示第i堆石子的个数(1<=i<=N)。

Output

对于每组数据输出一个正整数,即最小得分

Sample Input

7
13
7
8
16
21
4
18

Sample Output

239

思路

该题设f[i][j]为从i到j的所有石子合并成一堆的最小得分,那么有2种方法可以完成:

  1. 先枚举长度,再枚举起点
  2. 先枚举起点,再枚举终点
    也可以设f[i][j]为从第i个起,后面的j个数合并的最小代价,然后枚举长度和边界
    我用了第1种:
    f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] + 第 1 至 j 的 和 − 第 1 至 i − 1 的 和 ) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+第1至j的和-第1至i-1的和) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+1j1i1)
    (2<=l<=n,1<=i<=n&&j<=n,j=i+l)
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300],s[300],dp[300][300];
int main()
{
	cin>>n;
	for (int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for (int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
	for (int l=2;l<n;l++) for (int i=1,j=i+l;j<=n&&i<=n;i++,j=i+l)
	{
		dp[i][j]=0x7f7f7f7f;
		for (int k=i;k<j;k++)
		{
			dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+s[j]-s[i-1]);
		}
	}
	cout<<dp[1][n];
	return 0;
}

第2种方法也可以:

#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300],s[300],dp[300][300];
int main()
{
 cin>>n;
 for (int i=1;i<=n;i++)
 {
  cin>>a[i];
 }
 for (int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
 for (int i=n-1;i>=1;i--) for (int j=i+1;j<=n;j++)
 {
  dp[i][j]=0x7f7f7f7f;
  for (int k=i;k<j;k++)
  {
   dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+s[j]-s[i-1]);
  }
 }
 cout<<dp[1][n];
 return 0;
}

第3种:
f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i + k ] [ j − k ] + f [ i ] [ k ] + 第 1 至 j + i − 1 的 和 − 第 1 至 i − 1 的 和 ) f[i][j]=min(f[i][j],f[i+k][j-k]+f[i][k]+第1至j+i-1的和-第1至i-1的和) f[i][j]=min(f[i][j],f[i+k][jk]+f[i][k]+1j+i11i1)
代码:

#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300],s[300],dp[300][300];
int main()
{
 cin>>n;
 for (int i=1;i<=n;i++)
 {
  cin>>a[i];
 }
 for (int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
 for (int l=1;l<=n;l++) for (int i=1;i<=n;i++)
 {
  dp[i][l]=0x7f7f7f7f;
  for (int k=1;k<l;k++)
  {
   dp[i][l]=min(dp[i][l],dp[i+k][l-k]+dp[i][k]+s[l+i-1]-s[i-1]);
  }
  if (l==1) dp[i][l]=0;
 }
 cout<<dp[1][n];
 return 0;
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服