石子合并

来源:互联网 发布:js展开收起效果 编辑:程序博客网 时间:2024/06/05 19:23

题目描述

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

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

输入输出格式

输入格式:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.

输入输出样例

输入样例#1: 复制
4
4 5 9 4
输出样例#1: 复制
43
54

一道比较经典的区间(环形)dp了

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,a[1001],sum[1001],s[1001],f[1001][1001],g[1001][1001];int ansmax,ansmin=0x7fffffff;int main(){    scanf("%d",&n);    for (int i=1; i<=n; i++)    {        scanf("%d",&a[i]); a[i+n]=a[i];    }    for (int i=1; i<=2*n; i++)        sum[i]=sum[i-1]+a[i];    for (int step=0; step<n; step++)    {        memset(f,0,sizeof(f));        memset(g,0x7f,sizeof(g));        for (int i=1; i<=n; i++)        {            s[i]=sum[i+step]-sum[step];//          printf("%d ",s[i]);            g[i][i]=0;        }//      printf("\n");        for (int j=2; j<=n; j++)            for (int i=j-1; i>=1; i--)                for (int k=i; k<=j-1; k++)                {                    f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);                    g[i][j]=min(g[i][j],g[i][k]+g[k+1][j]+s[j]-s[i-1]);                }        ansmin=min(ansmin,g[1][n]);        ansmax=max(ansmax,f[1][n]);    }    printf("%d\n%d",ansmin,ansmax);    return 0;}/*44 5 9 44354*/
原创粉丝点击