石子合并2

本文探讨了在一个圆形操场周围摆放石子堆的问题,通过动态规划算法实现了对这些石子堆进行合并操作,以获得最小和最大得分的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目描述】

在一个圆形操场的四周摆放N堆石子(N ≤ 100),现要将石子有次序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。编一程序,读入堆数N及每堆石子数(≤ 100)选择一种合并石子的方案,分别得到合并这N堆石子为一堆,可以得到的最大得分和最小得分。

【输入描述】

输入包含多个例子。第一行为N,即石子堆的数目,以下一行为N个整形,分别代表每堆石子的数目。当N=0时,输入结束。

【输出描述】

对每个例子,输出其最小得分和最大得分,这两个数值以空格间隔开,每个例子占一行。

【输入样例】

6

30 35 15 5 10 20

3

1 2 3333

6

3 4 5 6 7 8

0

【输出样例】

275 475

3339 6671

84 125

源代码:

#include<cstdio>
#include<algorithm>
#define INF 1000000000
using namespace std;
int n,Max=0,Min=INF,i[101],f1[201][201],f2[201][201],sum[201]; //注意数据范围,f1[i][j]表示[i,j]合并的最小代价,f2[i][j]表示最大代价。
void DP()
{
    for (int a=2;a<=n;a++)
      for (int b=1;b<=(n<<1)-a+1;b++)
      {
          int t=b+a-1;
          f1[b][t]=INF;
          for (int c=b;c<t;c++)
          {
              f1[b][t]=min(f1[b][t],f1[b][c]+f1[c+1][t]+sum[t]-sum[b-1]);
              f2[b][t]=max(f2[b][t],f2[b][c]+f2[c+1][t]+sum[t]-sum[b-1]);
      }
} }
int main() { scanf("%d",&n); for (int a=1;a<=n;a++) { scanf("%d",&i[a]); i[a+n]=i[a]; } for (int a=1;a<=(n<<1);a++) //前缀和处理。 sum[a]=sum[a-1]+i[a]; DP(); for (int a=1;a<=n;a++) { Min=min(Min,f1[a][a+n-1]); Max=max(Max,f2[a][a+n-1]); } printf("%d\n%d",Min,Max); return 0; } /* 总体思想还是和链状合并类似的。 采取“断环为链”的思想,将DP长度扩至[1,2*n],便能囊括所有情况。 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值