设
m
x
[
l
,
r
]
mx[l,r]
mx[l,r] 表示区间
[
l
,
r
]
[l,r]
[l,r] 合并的最大得分,同理设
m
n
[
l
,
r
]
mn[l,r]
mn[l,r] 表示区间
[
l
,
r
]
[l,r]
[l,r] 合并得到的最小得分。
m
x
[
l
,
r
]
=
max
l
≤
k
<
r
{
m
x
[
l
,
k
]
+
m
x
[
k
+
1
,
r
]
}
+
∑
i
=
l
r
a
i
mx[l,r]=\max\limits_{l\leq k<r}\{mx[l,k]+mx[k+1,r]\}+\sum_{i=l}^ra_i
mx[l,r]=l≤k<rmax{mx[l,k]+mx[k+1,r]}+i=l∑rai
m
n
[
l
,
r
]
=
min
l
≤
k
<
r
{
m
n
[
l
,
k
]
+
m
n
[
k
+
1
,
r
]
}
+
∑
i
=
1
r
a
i
mn[l,r]=\min\limits_{l\leq k<r}\{mn[l,k]+mn[k+1,r]\}+\sum_{i=1}^ra_i
mn[l,r]=l≤k<rmin{mn[l,k]+mn[k+1,r]}+i=1∑rai
初值:
m
x
mx
mx 全为
0
0
0,
∀
x
∈
[
1
,
2
N
]
,
m
n
[
x
,
x
]
=
0
\forall x\in[1,2N],mn[x,x]=0
∀x∈[1,2N],mn[x,x]=0,其余全为
+
∞
+\infty
+∞
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[210],mx[210][210],mn[210][210],sum[210],n,maxn,minn;
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&n);memset(mn,0x3f,sizeof(mn));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),a[i+n]=a[i];
for(int i=1;i<=2*n;i++)
mn[i][i]=0,sum[i]=sum[i-1]+a[i];
for(int len=2;len<=n;len++)
for(int l=1;l<=2*n-len;l++)
{
int r=l+len-1;
for(int k=l;k<r;k++)
mn[l][r]=min(mn[l][r],mn[l][k]+mn[k+1][r]),mx[l][r]=max(mx[l][r],mx[l][k]+mx[k+1][r]);
mn[l][r]+=sum[r]-sum[l-1];mx[l][r]+=sum[r]-sum[l-1];
}
minn=0x3f3f3f3f;
for(int i=1;i<=n;i++)
maxn=max(maxn,mx[i][i+n-1]),minn=min(minn,mn[i][i+n-1]);
printf("%d\n%d\n",minn,maxn);
return 0;
}
总结
处理环形问题常常翻倍拼接到后面