day38 完全背包

### 9.14 52. 携带研究材料(第七期模拟笔试)
题目描述
小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的重量,并且具有不同的价值。
小明的行李箱所能承担的总重量为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料可以选择无数次,并且可以重复选择。

输入描述
第一行包含两个整数,N,V,分别表示研究材料的种类和行李空间 
接下来包含 N 行,每行两个整数 wi 和 vi,代表第 i 种研究材料的重量和价值

输出描述
输出一个整数,表示最大价值。
输入示例
4 5
1 2
2 4
3 4
4 5
输出示例
10
提示信息
第一种材料选择五次,可以达到最大值。

数据范围:
1 <= N <= 10000;
1 <= V <= 10000;
1 <= wi, vi <= 10^9.
File:///D:/School/T195ComputerScienceConversion/24fall/30680WebAppDevelopment/practical/practical1/e3.html
 完全背包 
https://www.bilibili.com/video/BV1uK411o7c9
https://programmercarl.com/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85.html   

dp`[j] : 容量为j的背包能装物品的最大价值

dp`[j] = Math.max((dp[j-weight[i]]+value[i]),dp[j])
dp`[0] = 0;

自己写的时候碰到的问题:如何让一个物品被多次取用?
改用正序遍历。
之前用倒序遍历就是为了让每个物品只被添加一次。

纯完全背包既可以先遍历物品再遍历背包,又可以先遍历背包再遍历物品。
先遍历物品再遍历背包:
![[bagIterating1.png]]
先遍历背包再遍历物品
![[bagIterating2.png]]

```java
public class bag03TakeResearchMaterial {  
    public static void main(String[] args) {  
        Scanner sc = new Scanner(System.in);  
        int type = sc.nextInt();  
        int bagSpace = sc.nextInt();  
  
        int[] weight = new int[type];  
        int[] value = new int[type];  
  
        for (int i = 0; i < type; i++) {  
            weight[i] = sc.nextInt();  
            value[i] = sc.nextInt();  
        }  
  
        int[] dp = new int[bagSpace+1];  
  
        for (int i = 0; i < type; i++) {  
            for (int j = weight[i]; j <= bagSpace; j++) {  
                dp[j] = Math.max((dp[j-weight[i]] + value[i]),dp[j]);  
            }  
        }  
  
        System.out.println(dp[bagSpace]);  
    }  
}
```

### 9.15 518. Coin Change II
You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.
Return the number of combinations that make up that amount. If that amount of money cannot be made up by any combination of the coins, return 0.
You may assume that you have an infinite number of each kind of coin.
The answer is guaranteed to fit into a signed 32-bit integer.
https://leetcode.cn/problems/coin-change-ii/description/
 518. 零钱兑换 II  
https://www.bilibili.com/video/BV1KM411k75j
https://programmercarl.com/0518.%E9%9B%B6%E9%92%B1%E5%85%91%E6%8D%A2II.html  

```java
public class coinChange2 {  
    public int change(int amount, int[] coins) {  
        int[] dp = new int[amount+1];  
        dp[0] = 1;  
  
        for (int i = 0; i < coins.length; i++) {  
            for (int j = coins[i]; j <= amount; j++) {  
                dp[j] += dp[j-coins[i]];  
//                System.out.print("coinIndex: " + i + ", coinDenominations: " + coins[i] +  
//                        ", bagCapacity: " + j + ", methods: " + dp[j] + "\t");  
            }  
            //System.out.println();  
        }  
  
        return dp[amount];  
    }  
}  
class coinChange2Test {  
    public static void main(String[] args) {  
        coinChange2 example = new coinChange2();  
        int amount = 6;  
        int[] coins = {7,4,5};  
        System.out.println(example.change(amount,coins));  
  
    }  
}
```
### 9.16 377. Combination Sum IV
Given an array of distinct integers nums and a target integer target, return the number of possible combinations that add up to target.
The test cases are generated so that the answer can fit in a 32-bit integer.
https://leetcode.cn/problems/combination-sum-iv/description/
 377. 组合总和 Ⅳ  
https://www.bilibili.com/video/BV1V14y1n7B6
https://programmercarl.com/0377.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C%E2%85%A3.html

如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。

```java
public class combinationSum4 {  
    public int combinationSum4(int[] nums, int target) {  
        int[] dp = new int[target+1];  
        dp[0] = 1;  
  
        //先遍历物品,再遍历背包可以得到组合数  
//        for (int i = 0; i < nums.length; i++) {  
//            for (int j = nums[i]; j <= target; j++) {  
//                dp[j] += dp[j-nums[i]];  
//            }  
//        }  
        //先遍历背包,再遍历物品可以得到排列数  
        for (int i = 0; i <= target; i++) {  
            for (int j = 0; j < nums.length; j++) {  
                if(i >= nums[j]){  
                    dp[i] += dp[i-nums[j]];  
                }  
            }  
        }  
  
        return dp[target];  
    }  
}  
class combinationSum4Test {  
    public static void main(String[] args) {  
        combinationSum4 example = new combinationSum4();  
        int[] nums = {1,2,3};  
        int target = 4;    
        System.out.println(example.combinationSum4(nums,target));  
    }  
}
```

### 9.17 57. 爬楼梯(第八期模拟笔试)
题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 
每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢? 
注意:给定 n 是一个正整数。

输入描述
输入共一行,包含两个正整数,分别表示n, m
输出描述
输出一个整数,表示爬到楼顶的方法数。
输入示例
3 2
输出示例
3
提示信息
数据范围:
1 <= m < n <= 32;
当 m = 2,n = 3 时,n = 3 这表示一共有三个台阶,m = 2 代表你每次可以爬一个台阶或者两个台阶。
此时你有三种方法可以爬到楼顶。
1 阶 + 1 阶 + 1 阶段
1 阶 + 2 阶
2 阶 + 1 阶
https://kamacoder.com/problempage.php?pid=1067
70. 爬楼梯 (进阶) 
这道题目 爬楼梯之前我们做过,这次再用完全背包的思路来分析一遍 
https://programmercarl.com/0070.%E7%88%AC%E6%A5%BC%E6%A2%AF%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85%E7%89%88%E6%9C%AC.html  

```java
public class climbStairs {  
    public static void main(String[] args) {  
        Scanner sc = new Scanner(System.in);  
  
        int stairs = sc.nextInt();  
        int steps = sc.nextInt();  
  
        int[] dp = new int[stairs+1];  
        dp[0] = 1;  
  
        for (int i = 0; i <= stairs; i++) {  
            for (int j = 1; j <= steps; j++) {  
                if(i >= j){  
                    dp[i] += dp[i-j];  
                }  
            }  
        }  
        System.out.println(dp[stairs]);  
    }  
}
```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值