0-1背包问题 ?前提知识
框架:
int dp[][] = new int[n+1][m+1];
int dp[0][...] = 0;
int dp[...][0] = 0;
for i in [1...n]
????for j in [1...m]
????//取两种选择的最优解
????dp[i][w]= max(
????????将重量a价值b的物品装进背包,
????????不将重量a价值b的物品装进背包)
????return [n][w];
?
代码如下:
int knapsack(int W,int N,int[] wt,int[] val){
?? ?//定义dp数组,初始化 dp[2][3] = 3 表示可以承重为3的前2个东西选择性放进背包的最优解(最大价值)为3
?? ?int[][] dp = new int[N+1][W+1];
?? ?for(int i=1;i<N;i++){
?? ??? ?for(int w=1;w<=W;w++){
?? ??? ??? ?if(w-wt[i-1]<0){
?? ??? ??? ??? ?dp[i][w] = dp[i-1][w];
?? ??? ??? ?}else{
?? ??? ??? ??? ?dp[i][w] = Math.max(
?? ??? ??? ??? ?dp[i-1][w-wt[i-1]]+val[i-1],
?? ??? ??? ??? ?dp[i-1][w]
?? ??? ??? ?);
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?)
?? ??? ?}
?? ?}
?? ?return dp[N][W];
}
Leetcode416:分割等和子集
class?Solution?{
? ?public?boolean?canPartition(int[]?nums) {
? ? ? ?int?n?=?nums.length;
? ? ? ?int?sum?=?0;
? ? ? ?for(int?i=0;i<n;i++){
? ? ? ? ? ?sum+=nums[i];
? ? ? }
? ? ? ?if(sum%2!=0){
? ? ? ? ? ?return?false;
? ? ? }
? ? ? ?sum?=?sum/2;
? ? ? ?boolean[][]?dp?=?new?boolean[n+1][sum+1];
? ? ? ?for(int?i?=?0;i<=?n;i++){
? ? ? ? ? ?dp[i][0]?=?true;
? ? ? }
?
? ? ? ?for(int?i?=1;i<=n;i++){
? ? ? ? ? ?for(int?j?=1;j<=sum;j++){
? ? ? ? ? ? ? ?if(j-nums[i-1]<0){
? ? ? ? ? ? ? ? ? ?dp[i][j]?=?dp[i-1][j];
? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ?dp[i][j]?=?dp[i-1][j]?||?dp[i-1][j-nums[i-1]];
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? }
? ? ? ?return?dp[n][sum];
? }
}
Leetcode518:零钱兑换II
class?Solution?{
? ?public?int?change(int?amount,?int[]?coins) {
? ? ? ?int?n?=?coins.length;
? ? ? ?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++){
? ? ? ? ? ? ? ?if(j-coins[i-1]<0){
? ? ? ? ? ? ? ? ? ?dp[i][j]?=?dp[i-1][j];
? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ?dp[i][j]?=?dp[i-1][j]+dp[i][j-coins[i-1]];
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? }
? ? ? ?return?dp[n][amount];
? }
}
|