问题描述 

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

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

  同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:

  有一个数字串:, 当N=,K=1时会有以下两种分法:

  *=
  *=   这时,符合题目要求的结果是:*=   现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。 输入格式   程序的输入共有两行:
  第一行共有2个自然数N,K(≤N≤,≤K≤)
  第二行是一个长度为N的数字串。 输出格式   输出所求得的最大乘积(一个自然数)。   样例输入   
  
样例输出

记:

由于DP题目的解法仍不熟悉,故上网搜寻解题思路

(代码参考:https://blog.csdn.net/fine_rose/article/details/63685548)

参考代码:

 #include <stdio.h>
#define MIN(X,Y) (X)<(Y)?(X):(Y) int n,k;
long long num[] = {};
long long dp[][] = {};/*可使用的数字,*号的个数*/ long long cut(int l,int r)
{
int i;
long long end = ;
for (i = l ; i <= r ;i ++)
{
end = end* + num[i];
}
return end;
} void init()
{
int i;
char tmp[] = {};
scanf("%d %d",&n,&k);
scanf("%s",&tmp);
for (i = ; i <= n ; i ++)
{
num[i] = tmp[i-]-'';
}
for (i = ; i <= n ; i ++)
{
dp[i][] = cut(,i);
}
return ;
} void find()
{
int i,j;
int a,b; for (i = ; i <= n ; i ++)/*枚举能使用数字(1-i),(至少需要2数字才可添加*号)*/
{
j = MIN(i-,k);/*枚举在能使用数字中最多能放的*个数*/
for (a = ; a <= j ; a ++)/*枚举j个乘号情况下的数字分布*/
{
for (b = a ; b < i ; b ++)/*枚举在能使用数字内的不同组合*/
{
if (dp[b][a-]*cut(b+,i) > dp[i][a])
{
dp[i][a] = dp[b][a-]*cut(b+,i);/*存放最大值*/
}
}
}
} return ;
} int main(void)
{
init();
find();
printf("%lld",dp[n][k]);
return ;
}

在过完思路后,可以发现由于会遍历不同长度下的可能结果,而我们仅仅是要长度为n时的最大乘积,显然程序做了大量的无用功

而到这里,思路也有所启发

从题目中,我们可以得到的隐藏条件是n>1,且n>k

而题目的样例输入

4 2

1231

指两个乘号,放在4个数据中间(左右两端不能放),那么

第一个乘号的可能出现位置为:1*2*3*1

第二个乘号的可能出现位置为:12*3*1 (至少已放了一个乘号)

显然,后面的乘号出现位置前面的乘号的位置有关系,可以通过标记摆放乘号,并用递归遍历不同的乘号(dfs)

这样,我们就可以得到一种情况下的数字分割

通过查乘号的出现位置,完成数字之间的相乘,并比较最大值,将最大值保存

改进代码:

 #include <stdio.h>
#define MAX 46 int n,k;
long long num[MAX] = {};/*每一位的数据存储*/
int vis[MAX] = {}; /*每一位乘号的使用标记*/
long long max = ; /*最大值存储*/ void init()
{
int i;
char tmp[MAX] = {};
scanf("%d %d",&n,&k);
scanf("%s",&tmp);
for (i = ; i <= n ; i ++)
{
num[i] = tmp[i-]-'';
}
return ;
} long long cut(int l,int r)
{
int i;
long long end = ;
for (i = l ; i <= r ;i ++)
{
end = end* + num[i];
}
return end;
} void dfs(int x)
{
/*隐藏条件:N>1,N>K*/
int i;
int a,b;/*乘号分割下的数字左右下标*/
long long tmp; if (x > k)/*乘号使用完毕*/
{
a = ,b = ;
tmp = ;
/*计算该次搜索中的数字分割后的乘积*/
for (i = ; i < n ; i ++)
{
if (vis[i])
{
b = i;
tmp *= cut(a+,b);
a = b;
}
}
tmp *= cut(a+,n);
if (tmp > max)
{
max = tmp;
}
return ;
} for (i = x ; i < n ; i ++)/*遍历不同位置的乘号*/
{
if (!vis[i])/*当前位置的乘号未使用*/
{
vis[i] = ;
dfs(x+);
vis[i] = ;
}
} return ;
} int main(void)
{
init();
dfs();
printf("%lld",max);
return ;
}

ALGO-17_蓝桥杯_算法训练_乘积最大(DP)的更多相关文章

  1. Java实现 蓝桥杯VIP 算法训练 阿尔法乘积

    蓝桥杯–阿尔法乘积 问题描述 计算一个整数的阿尔法乘积.对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身:否则的话,x的阿尔法乘积就等于它的各位非0的 ...

  2. [蓝桥杯]ALGO-20.算法训练_求先序排列

    问题描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度<=). 输入格式 两行,每行一个字符串,分别表示中序和后序排列 输出格式 一个字符串,表示所求 ...

  3. [蓝桥杯]ALGO-16.算法训练_进制转换

    问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...

  4. [蓝桥杯]ALGO-15.算法训练_旅行家的预算

    问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2.出发点每升汽油价格P和沿 ...

  5. [蓝桥杯]ALGO-124.算法训练_数字三角形

    问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和最大. ●每一步可沿左斜线向下或右斜线向下走: ●<三角形行数≤: ●三角 ...

  6. [蓝桥杯]ALGO-122.算法训练_未名湖边的烦恼

    问题描述 每年冬天,北大未名湖上都是滑冰的好地方.北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩. 每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个.现在 ...

  7. [蓝桥杯]ALGO-116.算法训练_最大的算式

    问题描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号 ...

  8. [蓝桥杯]ALGO-101.算法训练_图形显示

    问题描述 编写一个程序,首先输入一个整数,例如5,然后在屏幕上显示如下的图形(5表示行数): * * * * * * * * * * * * * * * 题目描述 代码如下: #include < ...

  9. [蓝桥杯]ALGO-97.算法训练_排序

    题目描述: 问题描述 编写一个程序,输入3个整数,然后程序将对这三个整数按照从大到小进行排列. 输入格式:输入只有一行,即三个整数,中间用空格隔开. 输出格式:输出只有一行,即排序后的结果. 输入输出 ...

  10. [蓝桥杯]ALGO-92.算法训练_前缀表达式

    问题描述 编写一个程序,以字符串方式输入一个前缀表达式,然后计算它的值.输入格式为:“运算符 对象1 对象2”,其中,运算符为“+”(加法).“-”(减法).“*”(乘法)或“/”(除法),运算对象为 ...

随机推荐

  1. AI之路,第二篇:python数学知识2

    第二篇:python数学知识2 线性代数 导入相应的模块: >>> import numpy as np     (数值处理模块)>>> import scipy ...

  2. [LeetCode&Python] Problem 447. Number of Boomerangs

    Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of po ...

  3. tinyxml2使用

    项目中遇到一个问题,C/C++需要与JAVA通信,JAVA方已经使用了XML序列化传输.本可以考虑JSON/GOOGLE PROTOCOL BUFFER的,但为了使JAVA方不做过多改动,坚持使用XM ...

  4. unity 实现调用Windows窗口/对话框交互

    Unity调用Window窗口 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分 ...

  5. npm常规命令行集合

    最近在摸索vue-cli脚手架的安装,中间用到了一些node的npm命令行,进行了一些整理,并且这个会一直搜集整理更新! 1,常规文件操作命令 cd..                   返回当前文 ...

  6. 《DSP using MATLAB》Problem 5.10

    代码: 第1小题: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Out ...

  7. 写出一个程序,接受一个由字母和数字组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数。不区分大小写。java算法

    知识点一:equalsIgnore 1.使用equals( )方法比较两个字符串是否相等.它具有如下的一般形式: boolean equals(Object str) 这里str是一个用来与调用字符串 ...

  8. Go Example--原子计数器

    package main import ( "fmt" "runtime" "sync/atomic" "time" ) ...

  9. 【BZOJ3144】【HNOI2013】切糕

    总算做了一道2011以后的省选题了……原题: 图片题面好评! P,Q,R≤40,0≤D≤R,给出的所有的不和谐值不超过1000. 文本样例好评! 恩这个是听妹主席讲过后会写的,首先把每个点拆成链,那么 ...

  10. initrd in linux 2.6.32.27

    2.6.32.27可以不指定initrd选项 如果指定initrd选项,则自动调用initrd内的linuxrc或init进行一切必要的初始化.Kernel启动参数全部会作为变量传递给这两个脚本.如r ...