问题描述: 在一个圆形操场的四周摆放着n堆石子. 现在要将石子有次序地合并成一堆. 规定每次只能选相邻的2堆石子合并成一堆, 并将新的一堆石子数记为该次合并的得分. 试设计一个算法, 计算出将n堆石子合并成一堆的最小得分和最大得分.
算法设计: 对于给定n堆石子, 计算合并成一堆的最小得分和最大得分.
数据输入: 第1行是正整数n, 1<=n<=100, 表示有n堆石子. 第2行有n个数, 分别表示n堆石子的个数.
结果输出: 第1行是最小得分, 第2行是最大得分.
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
#include<iostream>
#include<algorithm>
#define sum(j,k) tt[k]-tt[j-1]
using namespace std;
int n;
int se[205],tt[205],dpx[205][205],dpn[205][205];//环状石头,开两倍
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>se[i];
se[i+n]=se[i];
}
for(int i=1;i<=2*n;i++) tt[i]=tt[i-1]+se[i]; //预处理石头加和
for(int i=1;i<n;i++) //步长
{
for(int j=1,k=j+i; j<2*n && k<2*n ; j++,k=j+i)
{
dpn[j][k]=0x7fffffff;
for(int w=j;w<k;w++)
{
dpx[j][k] = max(dpx[j][k],dpx[j][w]+dpx[w+1][k]+sum(j,k));
dpn[j][k] = min(dpn[j][k],dpn[j][w]+dpn[w+1][k]+sum(j,k));
}
}
}
int maxx=0,minn=0x7fffffff;
for(int i=1;i<=n;i++)
{
maxx=max(maxx,dpx[i][i+n-1]);
minn=min(minn,dpn[i][i+n-1]);
}
cout<<minn<<endl<<maxx<<endl;
return 0;
}