石子合并

#include<bits/stdc++.h>  
using namespace std;   
int n,ans1,ans2,f1[300][300],f2[300][300];  
int sum[300],num[300];  
int main()  
{   
    scanf("%d",&n);  
    for(int i=1;i<=n+n;i++)
    {  
        scanf("%d",&num[i]);  
        num[i+n]=num[i];  
        sum[i]=sum[i-1]+num[i];  
    }  
    for(int p=1;p<n;p++)  
    {  
        for(int i=1,j=i+p;j<n*2 && i<n*2;i++,j=i+p)  
        { 
            f1[i][j]=1e9;  
            for(int k=i;k<j;k++)  
            {  
                f1[i][j] = min(f1[i][j], f1[i][k]+f1[k+1][j]+sum[j]-sum[i-1]);   
                f2[i][j] = max(f2[i][j], f2[i][k]+f2[k+1][j]+sum[j]-sum[i-1]);  
            }  
        }  
    }  
    ans1=1e9;  
    for(int i=1;i<=n;i++)  
    {
        ans1=min(ans1,f1[i][i+n-1]); 
        ans2=max(ans2,f2[i][i+n-1]); 
    }  
    printf("%d\n%d",ans1,ans2);  
    return 0;  
}

计算f(i,j)的值时需要知道所有f(i,k)和f(k+1,j)的值;

而这两个中包含的元素的数量都小于f(i,j);

所以我们以len=j-i+1作为DP的阶段。

首先从小到大枚举len,然后枚举i的值,

根据len和i用公式计算出j的值,然后枚举k

查看题面

题目描述

在一个圆形操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆
规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出一个算法,计算出将 N 堆石子合并成 1 堆的最小得分和最大得分。

输入格式

数据的第 1 行是正整数 N,表示有 N 堆石子。
第 2 行有 N 个整数,第 i 个整数 ai 表示第 i 堆石子的个数。

输出格式

输出共 2 行,第 1 行为最小得分,第 2 行为最大得分。

输入 #1          输出 #1

4                43
4 5 9 4          54

说明/提示

1≤N≤100,0≤ai≤20
posted @ 2022-02-09 15:52  fervency  阅读(33)  评论(0编辑  收藏  举报