石子合并_DP

本文介绍了一种通过合并石子堆来计算最小和最大得分的方法。问题要求将n堆石子依次合并为一堆,每合并一次需计算得分。文章详细阐述了如何利用动态规划算法求解最小和最大得分。

石子合并

(stone.pas/c/cpp)

来源:某年NOI(去巴蜀交)

【问题描述】

    在huanxing一个操场上摆放着一行共n堆的石子。现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请编辑计算出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。

【输入文件】

输入第一行为n(n<1000),表示有n堆石子,第二行为n个用空格隔开的整数,依次表示这n堆石子的石子数量(<=1000)

【输出文件】

输出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。

【输入样例】

3

1 2 3

【输出样例】

9 11

#include 
   
    
#include 
    
     
#define dmax 9999

int n;
int a[1001];
int dp_max[1001][1001],dp_min[1001][1001];
int sum[1001][1001];

int main()
{
       scanf("%d",&n);

       memset(a,0,sizeof(a));
       memset(dp_max,0,sizeof(dp_max));
       memset(sum,0,sizeof(sum));

       int i;
       int z;
       for(i=1;i<=n;i++)
       {
              for(z=1;z<=n;z++)
              {
                     dp_min[i][z]=dmax;
              }
       }

       for(i=0;i<=n;i++)
              dp_min[i][1]=0;

       for(i=1;i<=n;i++)
       {
              scanf("%d",&a[i]);
       }

       int min=dmax,max=0;

       int j,k,t;
       for(i=1;i<=n;i++)
       {
              for(j=1;j<=n;j++)
              {
                     if(i+j-1>n)
                     {
                            t=(i+j-1)%n;

                            for(k=i;k<=n;k++)
                            {
                                   sum[i][j]+=a[k];
                             }
                            for(k=1;k<=t;k++)
                            {
                                   sum[i][j]+=a[k];
                            }
                     }
                     else
                     {
                            t=i+j-1;
                            for(k=i;k<=t;k++)
                            {
                                  sum[i][j]+=a[k];
                            }
                      }
              }
       }
       for(j=2;j<=n;j++)
       {
              for(i=1;i<=n;i++)
              {
                     for(k=1;k<=j-1;k++)
                     {
                            if(i+k>n)
                            {
                                   t=(i+k)%n;
                            }
                            else
                                   t=i+k;

                            if(dp_min[i][j]>dp_min[i][k]+dp_min[t][j-k]+sum[i][j])
                            {
                                   dp_min[i][j]=dp_min[i][k]+dp_min[t][j-k]+sum[i][j];

                                   if(min>dp_min[i][n])
                                   {
                                          min=dp_min[i][n];
                                   }
                            }

                            if(dp_max[i][j]
     
    
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值