P1043 数字游戏

题目链接: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;
} 
上一篇:120 - 算法 - 枚举算法 2692 假币问题


下一篇:从 0 学习 Python 0 - 120 大合集总结