动态规划----0-1背包问题(java实现)

0-1背包问题:                                                                                                                                                                                        若有物品n个,每个物品的价值Value,用vi表示,每个物品的重量weight用wi表示,其中vi和wi均为非负数。设背包的总容量为W,且W为非负数。现需要考虑的问题是:如何选择装入背包的物品,使装入背包的物品总价值最大。

(1)可以将背包的求解过程看作是一系列的决策过程,决定哪些物品应该放入背包,哪些物品不应该放入背包。如果一个问题的最优解包含n个物品,即x[i]=1,那么其余物品一定构成子问题1,2...n-1在容量W-wi时的最优解。如果不包含物品x[i]=0,那么其余物品一定构成子问题1,2...n-1在容量W-wi时的最优解。

(2)递归定义最优解的值                                                                                                                                                                      设c[i][w]表示背包的容量为w时i个物品导致的最优解的总价值,得到如下式子:                                                                                                                                  

代码如下:

import java.util.Scanner;
public class KnapSack {
    void  DP(int n, int W, int c[][], int wi[], int vi[]) {
        int i, w;
        for (i = 1; i <= n; i++) {
            System.out.print(i+"\t");
            for (w = 0; w <= W; w++) {
                if (wi[i] <= w) { //如果背包剩余的容量大于物品的重量
                    if (vi[i] + c[i - 1][w - wi[i]] > c[i - 1][w]){  //该物品放入重量为w的背包
                        c[i][w] = vi[i] + c[i - 1][w - wi[i]];
                    }
                    else {
                        c[i][w] = c[i - 1][w];//该物品不放入背包中
                    }
                }

                else c[i][w] = c[i-1][w];
                System.out.print(c[i][w]+"\t");
            }
            System.out.println();


        }



    }
    void outputDP(int n,int W,int w[] , int v[],int c[][]){
        int [] x = new int[n];
        int i;
        for(i=n;i>1;i--){
            if(c[i][W] == c[i-1][W]) {
                x[i-1] = 0;
            }
            else{
                x[i-1] =1;
                W=W-w[i-1];
            }
        }
        if(c[1][W]==0)
            x[0] = 0;
        else
            x[0] = 1;
        System.out.println("放入的物品的重量和价值为:");
        for(i=0;i<n;i++){
            if(x[i]==1)
                System.out.printf("重量:%d   价值:%d\n",w[i+1],v[i+1]);
        }
        System.out.print("最优的物品放入分布为:");
        for( i=0;i<n;i++){
            System.out.print(x[i]+"    ");
        }
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner=new Scanner(System.in);
        System.out.print("请输入背包的容量:");
        int W=scanner.nextInt();
        System.out.print("请输入物品的个数:");
        int num=scanner.nextInt();
        int [] w=new int[num+1];
        int [] v=new int[num+1];
        int [][] c=new int[num+1][W+1];
        System.out.print("请输入物品的重量和价值:");
        for(int i=1;i<=num;i++){
            w[i]=scanner.nextInt();
            v[i]=scanner.nextInt();
        }
        KnapSack a=new KnapSack();
        System.out.println("当物品数i时,背包容量为w时,背包的价值为c[i][w],如下所示:");
        for(int j=0;j<=W;j++)
            System.out.print("\t"+j);
        System.out.println();
        a.DP(num, W, c, w, v);
        a.outputDP(num, W, w, v, c);
        System.out.println("背包最优解的总价值为:"+c[num][W]);
    }

}

结果截图如下:

 

发布了14 篇原创文章 · 获赞 9 · 访问量 282

猜你喜欢

转载自blog.csdn.net/weixin_44392808/article/details/104216953