ssl1597-石子合并问题【区间dp练习】

Description
  在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。
编程任务:
  对于给定n堆石子,编程计算合并成一堆的最小得分和最大得分。


Input

输入包括多组测试数据,每组测试数据包括两行。

第1 行是正整数n,1<=n<=100,表示有n堆石子。
第2行有n个数,分别表示每堆石子的个数。



Output
对于每组输入数据,输出两行。

第1 行中的数是最小得分;第2 行中的数是最大得分。


Sample Input
4
4 4 5 9

Sample Output
43

54


解题思路

  看这题之前请补一下:http://blog.csdn.net/mr_wuyongcong/article/details/78815773

  这道题是石子合并的升级版,这里把改成了圆形,那么说明第一堆和最后一堆也可以合并,这道题我用了一种不同的方法。可以先把所有两个的和在一起,再把所有的三个的合在一起......以此类推。然后列出动态转移方程:

  mins=min(mins,f[i][k]+f[k+1][j]+s[j]-s[i-1])
  maxs=max(maxs,f1[i][k]+f1[k+1][j]+s[j]-s[i-1])

还是代码讲的清楚


代码

#include
#include
using namespace std;
int n,x,s[201],f[201][201],f1[201][201],maxs,mins,a[201];
int main()
{
  scanf("%d",&n);
  for (int i=1;i<=n;i++)
  {
    scanf("%d",&a[i]);
    a[n+i]=a[i];//环状相连
  }
  for (int i=1;i<=2*n;i++)
  s[i]=s[i-1]+a[i];//预处理不解释
  for (int ii=2;ii<=n;ii++)//如我所说↑
    for (int i=1;i<=2*n-ii+1;i++)//枚举开头
    {
int mins=2147483647,maxs=0,j=i+ii-1;//如我所说↑
for (int k=i;k
{
 mins=min(mins,f[i][k]+f[k+1][j]+s[j]-s[i-1]);
  maxs=max(maxs,f1[i][k]+f1[k+1][j]+s[j]-s[i-1]);

  //动态转移方程
}
f[i][j]=mins;//最小值存入
f1[i][j]=maxs;//最大值存入
    }
  int mins=2147483647,maxs=0;
  for (int i=1;i<=n;i++)
  {
    maxs=max(maxs,f1[i][i+n-1]); //求每个区域的最大值
    mins=min(mins,f[i][i+n-1]); //求每个区域的最小值
  }
  printf("%d\n%d",mins,maxs);//get√
}



你可能感兴趣的:(dp)