第九章 动态规划part07
- 70. 爬楼梯 (进阶)
import java.util.Scanner; class climbStairs{ public static void main(String [] args){ Scanner sc = new Scanner(System.in); int m, n; while (sc.hasNextInt()) { // 从键盘输入参数,中间用空格隔开 n = sc.nextInt(); m = sc.nextInt(); // 求排列问题,先遍历背包再遍历物品 int[] dp = new int[n + 1]; dp[0] = 1; for (int j = 1; j <= n; j++) { for (int i = 1; i <= m; i++) { if (j - i >= 0) dp[j] += dp[j - i]; } } System.out.println(dp[n]); } } }
思路:该题和背包问题一样,n为背包大小,1到m为物品的大小,要求装满背包有几种方法,而且是可以重复取物品。
- 322. 零钱兑换
class Solution { public int coinChange(int[] coins, int amount) { int max = Integer.MAX_VALUE; int[] dp = new int[amount + 1]; //初始化dp数组为最大值 for (int j = 0; j < dp.length; j++) { dp[j] = max; } //当金额为0时需要的硬币数目为0 dp[0] = 0; for (int i = 0; i < coins.length; i++) { //正序遍历:完全背包每个硬币可以选择多次 for (int j = coins[i]; j <= amount; j++) { //只有dp[j-coins[i]]不是初始最大值时,该位才有选择的必要 if (dp[j - coins[i]] != max) { //选择硬币数目最小的情况 dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1); } } } return dp[amount] == max ? -1 : dp[amount]; } }
思路:该题是完全背包问题,dp数组表示装满j需要的最少物品。该题不需要考虑组合或者排序,先遍历背包或者物品都可以。
- 279.完全平方数
class Solution { // 版本一,先遍历物品, 再遍历背包 public int numSquares(int n) { int max = Integer.MAX_VALUE; int[] dp = new int[n + 1]; //初始化 for (int j = 0; j <= n; j++) { dp[j] = max; } //如果不想要寫for-loop填充數組的話,也可以用JAVA內建的Arrays.fill()函數。 //Arrays.fill(dp, Integer.MAX_VALUE); //当和为0时,组合的个数为0 dp[0] = 0; // 遍历物品 for (int i = 1; i * i <= n; i++) { // 遍历背包 for (int j = i * i; j <= n; j++) { //if (dp[j - i * i] != max) { dp[j] = Math.min(dp[j], dp[j - i * i] + 1); //} //不需要這個if statement,因爲在完全平方數這一題不會有"湊不成"的狀況發生( 一定可以用"1"來組成任何一個n),故comment掉這個if statement。 } } return dp[n]; } } class Solution { // 版本二, 先遍历背包, 再遍历物品 public int numSquares(int n) { int max = Integer.MAX_VALUE; int[] dp = new int[n + 1]; // 初始化 for (int j = 0; j <= n; j++) { dp[j] = max; } // 当和为0时,组合的个数为0 dp[0] = 0; // 遍历背包 for (int j = 1; j <= n; j++) { // 遍历物品 for (int i = 1; i * i <= j; i++) { dp[j] = Math.min(dp[j], dp[j - i * i] + 1); } } return dp[n]; } }
思路:这道题和上一题思路一样,都是要求最小组成数,只不过是物品发生了变化。