On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).
Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of the floor,
and you can either start from the step with index 0, or the step with index 1.
Input: cost = [10, 15, 20]
Output: 15
Explanation: Cheapest is start on cost[1], pay that cost and go to the top.
题意:
递归三部曲:
static int[] COST;
int minCost = Integer.MAX_VALUE;
public int minCostClimbingStairs(int[] cost) {
COST = cost;
dfs(0, cost.length , 0);
dfs(1, cost.length , 0);
return minCost;
}
private void dfs(int i, int n, int curCost) {
if (i >= n) {
if (curCost < minCost) {
minCost = curCost;
}
return;
}
curCost += COST[i];
dfs(i+1, n, curCost);
dfs(i+2, n, curCost);
}
使用 memo 数组来记录某些已有计算,减少递归分支的产生。唯一要注意的是:因为我们可以从第 0/1 格楼梯开始,所以 memo 数组需要分别保存两种状态的计算结果。
public int minCostClimbingStairs(int[] cost) {
COST = cost;
memo = new int[cost.length];
Arrays.fill(memo, -1);
int choice1 = dfsWithMemo(0, cost.length);
Arrays.fill(memo, -1);
int choice2 = dfsWithMemo(1, cost.length);
return Math.min(choice1, choice2);
}
private int dfsWithMemo(int i, int n) {
if (i >= n) {
return 0; //跳出楼梯,返回即可
}
if (memo[i] == -1) {
memo[i] = COST[i] + Math.min(dfsWithMemo(i+1, n), dfsWithMemo(i+2, n));
}
return memo[i];
}
因为从某一格楼梯开始,子问题可能是前 1 格或前 2 格花费的最小者,存在最优子结构的求解,所以可用 dp 做。
dp[0] = cost[0]
,表示从第 0 格开始跳的体力花费。dp[1] = cost[1]
,表示从第 1 格开始跳的体力花费。dp[i]
的值代表直到走到第 i 格楼梯最小体力花费。dp[i] = cost[i] + min(dp[i-1], dp[i-2])
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
String[] ss = sc.next().split(",");
int n = ss.length, w[] = new int[n], f[] = new int[n+1];
for (int i = 0; i < n; i++) w[i] = Integer.parseInt(ss[i]);
for (int i = 2; i <= n; i++) {
f[i] = Math.min(f[i-1] + w[i-1], f[i-2] + w[i-2]);
}
System.out.println(f[n]);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}