题目描述
在一个圆形操场的四周摆放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题,第一次写区间dp,真尼玛玄学
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int a[205],sum[205];
int opt1[205][205],opt2[205][205];
int sun(int i,int j)//求出区间[i,j]的和
{
return sum[j]-sum[i-1];
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[n+i]=a[i];//变成环状
}
for(int i=1;i<=2*n;i++)//方便求区间和
sum[i]=sum[i-1]+a[i];
for(int l=1;l<n;l++)//枚举区间长度
for(int i=1,j=i+l;i<2*n&&j<2*n;i++,j=i+l)//枚举各个长度为l的区间
{
opt2[i][j]=inf;
for(int k=i;k<j;k++)//区间上求最优解
{
opt1[i][j]=max(opt1[i][j],opt1[i][k]+opt1[k+1][j]+sun(i,j));
opt2[i][j]=min(opt2[i][j],opt2[i][k]+opt2[k+1][j]+sun(i,j));
}
}
int min_ans=inf, max_ans=0;
for(int i=1;i<=n;i++)//找到长度为n的最优区间 取其值
{
max_ans=max(max_ans,opt1[i][i+n-1]);
min_ans=min(min_ans,opt2[i][i+n-1]);
}
cout<<min_ans<<endl<<max_ans;
return 0;
}