文章最前: 我是Octopus,这个名字来源于我的中文名--章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github ;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的动态,一起学习,共同进步。
完全背包问题:
有n个物品,重量分别为weight[i] (0-n-1),每个物品有无限多个,选择一些物品装入背包,在不超过背包重量w的前提下:
完全背包:每个阶段一个物品怎么装入背包,0个,1个,k个
需要求解的问题:
1)背的可装物品总重量的最大值是多少?
2)是否能装满整个背包
3)正好装满背包最少需要多少物品
4)装满背包有多少种方法
“零钱兑换” 题目是最优问题322:最少要多少物品能填满背包
/**
* 硬币兑换
*
* @param coins 硬币兑换
* @param amount 数量
* @return 最小数量
*/
public int coinChange(int[] coins, int amount) {
if (coins == null || coins.length < 1) {
return 0;
}
int n = coins.length;
// 定义动态数组
int[][] dp = new int[n + 1][amount + 1];
// 初始化数dp组
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= amount; j++) {
dp[i][j] = 10001;
}
}
for (int i = 0; i <= n; i++) {
dp[i][0] = 0;
}
// 状态转移方程
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= amount; j++) {
int w = coins[i - 1];
if (w > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - w] + 1);
}
}
}
// 找到一个问题,发现是三元运算符用错了???(以后三元运算法要少用)
if (dp[n][amount] >= 10001) {
return -1;
} else {
return dp[n][amount];
}
}
“零钱背包2”是计数问题518:填满背包有多少种方法
/**
* 动态规划
*
* @param amount 数量
* @param coins 数组
* @return 次数
*/
public int change(int amount, int[] coins) {
if (coins == null || coins.length < 1) {
return 0;
}
int n = coins.length;
// 定义dp数组
int[][] dp = new int[n + 1][amount + 1];
// 初始化数组
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= amount; j++) {
int w = coins[i - 1];
if (w > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j] + dp[i][j - w];
}
}
}
return dp[n][amount];
}