1. 剪绳子
题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述:
输出答案。
示例1
输入
8
输出
18
题解
分析:对于长度n的绳子,我们都进行不剪、剪1、剪2…剪n-1。
对应结果应该是i*f[n-i],其中的f[i]代表长度为i的绳子的最优值。
所以对于任何长度的绳子,结果都可以表示成减去的长度*剩余长度最优值。去结果集中最大的,就是这个绳子的最优解。
可见这是一个递归求解的题。
使用暴力递归会超过限制。解决递归超限制的就是带备忘录的自顶向下DP或者自底向上的DP
import java.util.*;
public class Solution {
private Map<Integer, Integer> map = new HashMap<>();
public int cutRope(int target) {
map.put(1,1);
return back_t(target);
}
private int back_t (int target){
if(target == 1){
return 1;
}
if(target == 2){
return 2;
}
if(map.containsKey(target)){
return map.get(target);
}
int max = target;
for(int i=1; i<target; i++){
//int t = i*map.getOrDefault(target-i,back_t(target-i));
int t = i*back_t(target-i);
max = Math.max(max, t);
}
map.put(target, max);
return max;
}
}
单维度:
import java.util.*;
public class Solution {
private Map<Integer, Integer> map = new HashMap<>();
public int cutRope(int target) {
// 记录长度为j时的最大值
int [] dp = new int[target+1];
dp[0] = 0;
dp[1] = 1;
//全部初始化为不剪
for(int i = 1; i<=target; i++){
dp[i] = i;
}
for(int i=1; i<=target ; i++){
for(int j=1; j<=i; j++){
dp[i] = Math.max(dp[i], dp[i-j]*j);
}
}
return dp[target];
}
}
2. 机器人的运动范围
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
题解
可以使用DFS
public class Solution {
private int[][]mark ;
public int movingCount(int threshold, int rows, int cols)
{
mark = new int[rows][cols];
return dfs(0,0,rows,cols, threshold);
}
private int dfs(int rowIdx, int colIdx, int rows, int cols, int threshold){
//递归出口:越界
if(rowIdx>=rows || colIdx>=cols|| rowIdx<0 || colIdx<0){
return 0;
}
//递归出口:已访问、超过坐标限制
if(!check(rowIdx, colIdx, threshold) || mark[rowIdx][colIdx]==1){
return 0;
}
//标记访问
mark[rowIdx][colIdx] =1;
int sum = 1;
sum+=dfs(rowIdx+1, colIdx, rows, cols, threshold);
sum+=dfs(rowIdx-1, colIdx, rows, cols, threshold);
sum+=dfs(rowIdx, colIdx+1, rows, cols, threshold);
sum+=dfs(rowIdx, colIdx-1, rows, cols, threshold);
return sum;
}
private boolean check(int rowIdx, int colIdx, int threshold){
int sum = 0;
for(int i=1; i<=rowIdx; i=i*10){
rowIdx = rowIdx/i;
sum=sum+rowIdx%10;
}
for(int i=1; i<=colIdx; i*=10){
colIdx = colIdx/i;
sum = sum+ colIdx%10;
}
return sum>threshold? false:true;
}
}
BFS:
import java.util.*;
public class Solution {
public int movingCount(int threshold, int rows, int cols)
{
int sum=0;
int[][]mark = new int[rows][cols];
Queue<Integer> queueX = new LinkedList<>();
Queue<Integer> queueY = new LinkedList<>();
queueX.add(0);
queueY.add(0);
while(!queueX.isEmpty()){
int x = queueX.poll();
int y = queueY.poll();
if(!check(x,y,threshold) || x<0 || y<0 || x>=rows || y>=cols){
continue;
}
if(mark[x][y]==1)
continue;
// 标记已经访问
mark[x][y] = 1;
sum++;
queueX.add(x+1);
queueY.add(y);
queueX.add(x-1);
queueY.add(y);
queueX.add(x);
queueY.add(y+1);
queueX.add(x);
queueY.add(y-1);
}
return sum;
}
private boolean check(int rowIdx, int colIdx, int threshold){
int sum = 0;
for(int i=1; i<=rowIdx; i=i*10){
rowIdx = rowIdx/i;
sum=sum+rowIdx%10;
}
for(int i=1; i<=colIdx; i*=10){
colIdx = colIdx/i;
sum = sum+ colIdx%10;
}
return sum>threshold? false:true;
}
}