蓝桥杯:乘积最大II 暴力递归解法

蓝桥杯:乘积最大II 暴力递归解法

问题描述

今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:

设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。

同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312, 当N=3,K=1时会有以下两种分法:

3 * 12=36
31 * 2=62

这时,符合题目要求的结果是:31*2=62

现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

输入格式

程序的输入共有两行:
第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)
第二行是一个长度为N的数字串。

输出格式

输出所求得的最大乘积(一个自然数)。

样例输入

4 2
1231

样例输出

62

思路

我一看

N,K(6≤N≤40,1≤K≤6)
数长度不超过40,乘号不超过6个

如果暴力穷举每一个乘号的位置,粗略估计也才406种可能,那干脆就暴力了。。。

在区间l, r之间插入k个乘号,欲求最大值:

  • [l,r]之间空隙任意一个位置x插入乘号
  • 问题转化为求解:[l, x]表示的数字 * 【在[x+1, r]插入k-1个乘号的最大值】
  • 穷举所有可能的x,找出最大的情况即可

递归边界:
只有0个乘号,直接返回区间表示的数字即可
区间能插入的乘号数目小于要插入的数目,返回0

代码

#include 
#include 
#include 

using namespace std;

#define MAXLEN 49
#define char2int(c) ((int)(c - '0'))
int a[MAXLEN];
int N, K;

// 计算区间表示的数字
int sum(int l, int r)
{
	int s = 0;
	for(int i=l; i<=r; i++)
	{
		s *= 10;
		s += a[i];
	}
	return s;
}

int dfs(int l, int r, int k)
{
	// 没有乘号插入,直接返回数字
	if(k == 0)
	{
		return sum(l, r);
	}
	else if(r-l>=k && k>0)
	{
		int mmax = 0;
		for(int i=l; i<r; i++)
		{
			// 左边表示的数字
			int r1 = sum(l, i);
			// 在右边插入k-1个乘号
			int r2 = dfs(i+1, r, k-1);
			int res = r1 * r2;
			if(res > mmax)
			{
				mmax = res;
			}
		}
		return mmax;
	}
	else
	{
		return 0;
	}
}

int main()
{
	cin>>N>>K;
	for(int i=1; i<=N; i++)
	{
		char c;
		cin>>c;
		a[i] = char2int(c);
	}	
	cout<<dfs(1, N, K)<<endl;
	
	return 0;
}

你可能感兴趣的:(蓝桥杯,算法,dfs,递归,递归法)