1043 数字游戏

博客讲述了如何使用动态规划和前缀和方法解决一个关于环形数组分割成多个部分,求最大和最小乘积的问题。作者提到了破环为链的经典操作,并介绍了状态转移方程,通过不断枚举分割点来更新最大值和最小值。代码示例展示了具体的实现过程。
摘要由CSDN通过智能技术生成

1043 数字游戏

因为前缀和本来就是优化动态规划的方法,所以这一道题两个都得会,但是看第一眼的时候不明白和前缀和有什么关系
题目比较难理解
给定一个环数,要求分成k个方案,使得每个组的乘积之和最小和最大
首先我来列举一下操作吧
1.破环为链,这个操作非常的经典,而且在这个题很容易的看出来,给的数就是一个环,就是把数据进行两遍存储,如果想加深对破环为链的操作,必须得明白并查集的反集这一个东西,本菜鸡昨天才真正的启发式了
2.前缀和,前缀和不是万能的,但是前缀和真的很方便,节省了不少时间,适用于数据直接相加的题目,比如这个小可爱
另外我们在设计状态的时候加上一个枚举组数就好了
-----------------重新----------------------
先来说说题意:
给定一个环,给定n个数,将其分为m份
这m份的数相加,这m个结果的个数相乘,然后问这个最大最小是多少
破环为连
意思就是这个环形我们需要将其转化成一个线性的
其实这个题环不环不都一样吗,没什么区别
还有就是破环的区别就是在于首尾值的不变,所以我们需要将数组进行复制一份
1 2 3 1 2 3 这就是环的妙处

((a%10)+10)%10;//取各个位,为什么要+10进行取模?23%10=3 3+10=13 13%10=3
不影响操作,但比较保险

所以呢,这样的分割问题,什么划分了,规划了,分割了,都是需要枚举的
maxx[l][r][i] minn[l][r][i]分别表示l~r区间分割i的最大最小值
然后
min(minn[l][r][i],minn[l][k][i-1]*mod(a[r]-a[k])) 就是分割的方式

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
const int inf=2147483647;
const int SIZE=1e2+5;
int a[SIZE];
int minn[SIZE][SIZE][SIZE],maxx[SIZE][SIZE][SIZE];
int n,m;
int mod(int a)
{
	return ((a%10)+10)%10;//取各个位
	//为什么要+10进行取模?
	//23%10=3 3+10=13 13%10=3
	//不影响操作,但比较保险 
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		a[i+n]=a[i];//破环
		//1 2 3 1 2 3
	}
	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++)
			maxx[l][r][1]=minn[l][r][1]=mod(a[r]-a[l-1]);//l~r 分i段最大或最小值 
	for (int i=2;i<=m;i++)
      for (int l=1;l<=2*n;l++)
        for (int r=l+i-1;r<=2*n;r++)
          minn[l][r][i]=inf;//初始化无穷大 
	for(int i=2;i<=m;i++)//枚举组数 
		for(int l=1;l<=2*n;l++)//左端点 
			for(int r=l+i-1;r<=2*n;r++)//右端点 
				for(int k=l+i-2;k<r;k++)//枚举间断点 枚举分割 
				{
					minn[l][r][i]=min(minn[l][r][i],minn[l][k][i-1]*mod(a[r]-a[k]));//前缀和 
					maxx[l][r][i]=max(maxx[l][r][i],maxx[l][k][i-1]*mod(a[r]-a[k]));
				}
	int MAX=0,MIN=inf;
	for(int i=1;i<=n;i++)//比较出最大的 
	{
		MAX=max(MAX,maxx[i][i+n-1][m]);
		MIN=min(MIN,minn[i][i+n-1][m]);
	}
	cout<<MIN<<endl<<MIN;
	return 0;
 } 
 /*
 
 4 2
4
3
-1
2
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值