蓝桥杯算法训练:ALGO-17乘积最大

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

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

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

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

312=36
31
2=62

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

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

输入格式

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

输出格式

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

扫描二维码关注公众号,回复: 11117612 查看本文章

样例输入

4 2
1231
样例输出
62``

解题思路:使用dfs进行遍历,探索每一个数字之间是否注入节点(即为 * 号)。

比如说输入
3 1
123
先对1和2之间插入节点,res=1 * 2=2;st=2;node - - ;i=i+1
进入下一层,此处选择不加节点的话,则将res与上一个节点的乘数剥离:res=res/st= 2/2=1,然后st=“2”+“3”=23,再用res去乘新的st,得到res=1 * 23=23
此时node=0,将res放入list中。最后对得到的每一个res进行遍历,取出最大值即可。

为什么用long而不用int

因为我是对每一种情况都进行遍历,当st过大时或者参数超出int的最大值时,会报错java.lang.NumberFormatException(数字格式异常),且参数不能大于10位数字。所以使用了long类型,当然也可以使用
BigInteger。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class chengjizuida {

    static int n, k;
    static int[] tarr;//用于放置字符串中的各个数字
    static List<Integer> list=new ArrayList<>();
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] sarr = scanner.nextLine().split(" ");
        n = Integer.parseInt(sarr[0]);//有几个数
        k = Integer.parseInt(sarr[1]);//有几个节点
        String s = scanner.nextLine();
        tarr = new int[n];
        for (int i = 0; i < n; i++) {
            tarr[i] = s.charAt(i) - '0';
        }
        dfs(0,k,tarr[0],tarr[0]);
        int max=0;
        for (int i=0;i<list.size();i++){
            max=Math.max(max,list.get(i));
        }
        System.out.println(max);
    }
// i表示当前的字数 node表示还剩下多少个节点 res表示截至到当前的i,前面所有数字的乘积大小 st表示从上一个节点到当前i的所有数字的数字串                       
    private static void dfs(int i,int node ,long res,long st ) {
        if(node==0){//当节点为0时,将上一个st和余下的数字串合成,再去乘以res
            res=res/st;
            String str=new String();
            for (int j=i;j<n;j++){
                str+=tarr[j];
            }
            res=res*Integer.parseInt(str);
            int res1=(int)res;
            list.add(res1);
            return;
        }
        if (i+1<n&&tarr[i+1]!=0){//先进行不加节点
            i=i+1;
            long result1=res/st;
            long str=Long.parseLong(st+String.valueOf(tarr[i]));
            result1=result1*str;
            dfs(i,node,result1,str);
            node--;//此处进行加节点的操作
            long result2=res*tarr[i];
            str=tarr[i];
            dfs(i,node,result2,str);
        }else if (i+1<n&&tarr[i+1]==0){//这里需要额外判断tarr[i]==0;因为st不能为0(st为除数)
            i=i+1;
            long result1=res/st;
            long str=Long.parseLong(String.valueOf(st)+String.valueOf(tarr[i]));
            result1=result1*str;
            dfs(i,node,result1,str);
        }
    }
}

这个方法比较笨,只是自己的一点尝试,要优化的地方还有很多。其实这道题用动态规划来做会更好,此处只是提供另外一种思路,如果有错误,还请拨冗指正,十分感谢!

发布了11 篇原创文章 · 获赞 0 · 访问量 156

猜你喜欢

转载自blog.csdn.net/Kim_Linshuo/article/details/105445203
今日推荐