迭代思想写0-1背包问题

package Test1;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 采用迭代的思想,将背包的起始的重量 W 设置为0,W++ ,一直加到背包的最大的重量;
 */

public class beib01<i> {
     
    public static void main(String [] agrs){
     
    Scanner cin =new Scanner(System .in) ;
    System .out .println("输入物品总个数") ;
    int length = cin.nextInt() ;
    int []v = new int [length+1 ];
    int []w = new int [length+1 ];
    v[0]=0;w[0]=0;
    System .out .println("输入背包的总容量") ;
    int W=cin.nextInt() ;
    W=W+1;
    length =length +1;
    int [][]B= new int[length][W];
   // B[length][W-1]=0;
    for(int i=1;i<length;i++){
     
        System .out .println("输入第"+i+"个物品的价值") ;
        v[i]=cin.nextInt() ;
        System .out .println("输入第"+i+"个物品的重量") ;
        w[i]=cin.nextInt() ;
    }
    System .out .println(Arrays .toString(v) ) ;
    System .out .println(Arrays .toString(w) ) ;
    System .out .println(Knack(length ,W,v,w,B));
    }

    private static int Knack(int length, int W, int[] v, int[] w,int [][]B) {
     
        /**这部分方法相当于制作一张二维表
         * 迭代的意思的,从重量为j=1开始放起,一直放到它的最大容量
         * 放第一个,与不放第一个作比较,选择最大值,B[1][j]就是表示放前1个,当容量为j的时候的最大值
         * 放第二个,与不放第二个作比较,选择最大值,B[2][j]就是表示放前2个,当容量为j的时候的最大值
         * 其中,如果放第二个,那么它等于B[1][j-w[1]]+v[2],再次之前,已经记录下了B[1][j-w[1]]的最大值,所以当放到前二个时,
         * 这个值就可以直接用了;如果不放第二个,那么它等于B[1][j],两种结果相比较,最后将大的值保存在B[2][j];
         * 这其中,j的是变化,不停++,
         * 迭代的思想就是,放前i个物品,然后保存它每个j(注意是每个每个j!!!!)变化后,背包放进物品的最大值
         * 然后,放前i+1个时,它可以选择放或者不放,当它选择放时,j-w[i+1]为剩余重量,B[i][j-w[i+1]]这个值上一步已经算过了
         * 所以直接用;
         * 简单来说,是否放入当前物品,取决于当前所有的空间放了当前物品后所剩于空间下前面物品利用的剩余空间所放的最大价值+它本身价值
         * 与不放当前物品,当前所有空间放的前面所有价值相比较......
         * 放前i个物品的价值,受到放前i-1个价值的影响,有点斐波那契数的感觉...当时斐波那契数是一定会加上后一个数,而01背包则不一定
         * 因为前i-1的物品由于放了第i个物品,它的空间缩小了,所以它剩余的空间产生的最大值+v[i]的值也就不一定是最大值了
         * 我先前执着的认为,放了第i个物品后,那它肯定比没放的第i个物品的价值要大,那是因为我忽略了放了第i个物品后前i个物品的空间缩小了
         */
        int i=0,j=0;
        for( i=1;i<length ;i++)//从第i个物品开始放进去
            for (j=1; j <W; j++)//从背包等于1的,开始放物品进去,由于先前W已经+1过,所以现在是j<21;
            {
     
                 if(w[i]<=j){
     //先前这部分写成了w[i]
                    int value1=B[i-1][j-w[i]]+v[i];//表示他把第i个物品放进去了
                    //先前写成了value2=B[i][j];属于理解不到位,当不放第i个物品时,它的价值应该是B[i-1][j],表示前i-1个的最大价值
                     //再将它与放进去i个做比较,选择最大的一个作为B[i][j]的价值;
                    int value2=B[i-1][j];
                    B[i][j]=value1 >value2 ?value1 :value2 ;

                }
                 else
                     B[i][j]=B[i-1][j];
                System.out .println(B[i][j]) ;
                
            }
        return B[i-1][j-1];
    }


}

迭代思想写0-1背包问题_第1张图片

你可能感兴趣的:(迭代思想写0-1背包问题)