石子合并
#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