解题思路:

给出两种解题思路

1. dfs暴力搜索即可

2. 动态规划


注意事项:

dfs解题时思路就是不断向后枚举乘号出现的位置,注意边界条件和递归结束条件即可。

动态规划解题:

    定义:令dp[i][j]为前i个数字,使用j个乘号时得到的最大值。

    转移方程:dp[i][j] = max(dp[i][j], dp[m][j+1]+num[m, i])(m<i),其中num[m,i]为数字字符串下标m到j的子串对应的数字。

                    (说实话并不太会证明该问题的最优子结构= - =)   

    最终返回dp[N][K]即为所求。

    其实就是考虑在使用j-1个乘号时所有的历史最大历史数字串


参考代码:

import java.io.*;
import java.util.*;

// https://www.dotcpp.com/oj/problem1602.html
// 法1 暴力dfs
// 法2 动态规划
public class Main {
    static BufferedReader cin;
    static PrintWriter out;
    static int N;
    static int K;
    static String numStr;
    public static void main(String[] args) throws IOException{
        cin = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new OutputStreamWriter(System.out));
        String[] line = cin.readLine().split(" ");
        N = Integer.parseInt(line[0]);  // 长度为N
        K = Integer.parseInt(line[1]);  // 使用K个乘号
        numStr = cin.readLine();
        out.println(numStr.substring(0, 0));
        out.println(dfs(0, 1, 0, 1));
        out.println(DP());
        out.flush();
        out.close();
    }

    static long dfs(int s, int e, int count, long res){  // 当前开始结束下标, 选取总数, 当前左侧结果
        if(count == K){
            return res*Long.parseLong(numStr.substring(s));
        }
        if(e == numStr.length())
            return -1;
        long res1 = dfs(e, e+1, count+1, res*Long.parseLong(numStr.substring(s, e)));  // 添加乘号
        long res2 = dfs(s, e+1, count, res); // 不在e下标下添加乘号
        return Math.max(res1, res2);
    }

    static long DP(){
        // dp[i][j]表示i个字母, j个乘号时最大乘积
        long[][] dp = new long[N+1][K+1];  // dp数组
        for(int i = 1;i < N+1; i++){
            dp[i][0] = Long.parseLong(numStr.substring(0, i));
        }
        for(int i = 1; i <= N; i++){
            for(int j = 1; j <= K && j<i; j++){  // 乘号个数严格小于数字个数
                for(int m = 1; m < i; m++){
                    dp[i][j] = Math.max(dp[i][j], dp[m][j-1]*Long.parseLong(numStr.substring(m, i)));
                }
            }
        }
        return dp[N][K];


    }

}


点赞(0)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论