解题思路:
给出两种解题思路
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分
1 人评分
C语言程序设计教程(第三版)课后习题6.11 (C语言代码)浏览:565 |
WU-整除问题 (C++代码)浏览:648 |
WU-拆分位数 (C++代码)浏览:819 |
C语言程序设计教程(第三版)课后习题6.9 (C语言代码)浏览:760 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:701 |
Minesweeper (C语言描述,蓝桥杯)浏览:1176 |
母牛的故事 (C语言代码)浏览:1045 |
川哥的吩咐 (C语言代码)浏览:663 |
字符串比较 (C语言代码)浏览:770 |
C语言程序设计教程(第三版)课后习题5.7 (C语言代码)浏览:416 |