题目链接:https://www.luogu.com.cn/problem/P1043
题意:一个圆上的数分为m段,按题中所给式子求解最大值最小值
解题思路:区间dp,f[l][r][k]表示在区间[l,r]中分成k段的最大最小值。要考虑到首尾我们可以将数据存储两遍,构成链式。
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,a[120];
ll mx[120][120][120],mi[120][120][120];
ll mod(ll x){
return (x%10+10)%10;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i+n]=a[i];
}
for(int i=1;i<=2*n;i++){//前缀和
a[i]+=a[i-1];
}
for(int l=1;l<=2*n;l++){
for(int r=l;r<=2*n;r++){
mx[l][r][1]=mi[l][r][1]=mod(a[r]-a[l-1]);//初始化为未分段的情况
}
}
for(int k=2;k<=m;k++){
for(int l=1;l<=2*n;l++)
for(int r=l+k-1;r<=2*n;r++)
mi[l][r][k]=0x3f3f3f3f;
}
for(int k=2;k<=m;k++){//枚举分段数
for(int l=1;l<=2*n;l++)//枚举左端点
for(int r=l+k-1;r<=2*n;r++)//枚举右端点
for(int i=l+k-2;i<r;i++){//枚举断点
mx[l][r][k]=max(mx[l][r][k],mx[l][i][k-1]*mod(a[r]-a[i]));
mi[l][r][k]=min(mi[l][r][k],mi[l][i][k-1]*mod(a[r]-a[i]));
}
}
ll minn=0x3f3f3f3f,maxx=0;
for(int i=1;i<=n;i++){
minn=min(minn,mi[i][i+n-1][m]);
maxx=max(maxx,mx[i][i+n-1][m]);
}
cout<<minn<<'\n'<<maxx<<'\n';
return 0;
}