窃贼问题

窃贼问题是一个典型的最优化问题。窃贼问题的大意如下:

有一个窃贼带着一个背包去偷东西,房屋中共有5件物品,其重量和价值如下:

物品1: 6公斤,48元

物品2: 5公斤,40元

物品3: 2公斤,12元

物品4: 1公斤,8元

物品5: 1公斤,7元。

窃贼希望能够拿最大价值的东西,而窃贼的背包最多可装重量为8公斤的物品。那么窃贼应该装上述哪些物品才能达到要求呢?

 1. 窃贼问题算法

首先来分析一下窃贼问题。窃贼问题是关于最优化的问题,可使用动态规划的思想来解最优化问题。窃贼问题求解的操作过程如下:

(1)首先创建一个空集合。

(2)然后向空集合中增加元素,每增加一个元素就先求出该阶段最优解。

(3)继续添加元素,直到所有的元素都添加到集合中,最后得到的就是最优解。

采用上述思路,窃贼问题的求解算法如下:

(1)首先,窃贼将物品i试着添加到方案中。

(2)然后判断是否超重,若未超重,则继续添加下一个物品,重复第一步。

(3)若超重,则将该物品排除在方案之外,并判断此时所有未排除物品的价值是否小于已有最大值;如果满足,则不必再尝试后续物品了。

 可以按照此思路来编写相应的窃贼问题的求解算法,代码示例如下:

    static class GType{    //物品数据结构
        double value;    //价值
        double weight;    //重量
        char isSelect;    //是否选中到方案
    }
    
    static double maxvalue;    //方案最大价值
    static double totalvalue;    //物品总价值
    static double maxwt;    //窃贼能拿的最大重量
    static int num;        //物品数量
    static char[] seltemp;    //临时数组
    /**
     * 算法
     * @param goods 物品
     * @param i    下一个待选物品
     * @param wt 盗贼现拿物品重量
     * @param vt 可选物品总价值
     */
    static void backpack(GType[] goods,int i,double wt,double vt){
        int k;
        if(wt+goods[i].weight<=maxwt){    //将物品i包含在当前方案,判断重量小于等于限制重量
            seltemp[i]=1;    //选中第i个物品
            if(i<num-1){        //如果物品i不是最后一个物品
                backpack(goods,i+1,wt+goods[i].weight,vt);    //递归调用,继续添加物品
            }else{
                for(k=0;k<num;++k){
                    goods[k].isSelect=seltemp[k];
                }
                maxvalue=vt;    //保存当前方案的最大价值
            }
        }
        seltemp[i]=0;    //取消物品i的选择状态
        if(vt-goods[i].value>maxvalue){    //还可以继续添加物品
            if(i<num-1){
                backpack(goods,i+1,wt,vt-goods[i].value);    //递归调用
            }else{
                for(k=0;k<num;++k){
                    goods[k].isSelect=seltemp[k];
                }
                maxvalue=vt-goods[i].value;
            }
        }
    }

2. 窃贼问题求解

求解窃贼问题的完整代码如下:

package com.cn.suanfaquti;

import java.util.Scanner;

public class QieZeiQuestion {
    static class GType{    //物品数据结构
        double value;    //价值
        double weight;    //重量
        char isSelect;    //是否选中到方案
    }
    
    static double maxvalue;    //方案最大价值
    static double totalvalue;    //物品总价值
    static double maxwt;    //窃贼能拿的最大重量
    static int num;        //物品数量
    static char[] seltemp;    //临时数组
    /**
     * 算法
     * @param goods 物品
     * @param i    下一个待选物品
     * @param wt 盗贼现拿物品重量
     * @param vt 可选物品总价值
     */
    static void backpack(GType[] goods,int i,double wt,double vt){
        int k;
        if(wt+goods[i].weight<=maxwt){    //将物品i包含在当前方案,判断重量小于等于限制重量
            seltemp[i]=1;    //选中第i个物品
            if(i<num-1){        //如果物品i不是最后一个物品
                backpack(goods,i+1,wt+goods[i].weight,vt);    //递归调用,继续添加物品
            }else{
                for(k=0;k<num;++k){
                    goods[k].isSelect=seltemp[k];
                }
                maxvalue=vt;    //保存当前方案的最大价值
            }
        }
        seltemp[i]=0;    //取消物品i的选择状态
        if(vt-goods[i].value>maxvalue){    //还可以继续添加物品
            if(i<num-1){
                backpack(goods,i+1,wt,vt-goods[i].value);    //递归调用
            }else{
                for(k=0;k<num;++k){
                    goods[k].isSelect=seltemp[k];
                }
                maxvalue=vt-goods[i].value;
            }
        }
    }
    
    public static void main(String[] args) {
        double sumweight;
        int i;
        System.out.println("窃贼问题求解!");
        System.out.print("窃贼背包能容纳的最大重量:");
        Scanner input = new Scanner(System.in);
        maxwt=input.nextDouble();    //窃贼背包能容纳的最大重量
        System.out.print("可选物品数量:");
        num = input.nextInt();     //可选物品的数量
        GType[] goods=new GType[num];
        seltemp = new char[num];
        totalvalue=0;    //初始化总价值
        for(i=0;i<num;i++){
            GType t = new GType();
            System.out.print("输入第"+(i+1)+"号物品的重量和价值:");
            t.weight=input.nextDouble();
            t.value = input.nextDouble();
            totalvalue+=t.value;
            goods[i]=t;
        }
        System.out.print("\n背包最大能装的重量为:"+maxwt+"\n\n");
        for(i=0;i<num;i++){
            System.out.println("第"+(i+1)+"号物品重:"+goods[i].weight+",价值:"+goods[i].value);
            seltemp[i]=0;
        }
        maxvalue=0;
        backpack(goods,0,0.0,totalvalue);    //求解
        sumweight=0;
        System.out.println("\n可将以下物品装入背包,使背包的物品价值最大:");
        for(i=0;i<num;++i){
            if(goods[i].isSelect==1){
                System.out.println("第"+(i+1)+"号物品,重量:"+goods[i].weight+",价值:"+goods[i].value);
                sumweight+=goods[i].weight;
            }
        }
        System.out.println("\n总重量为:"+sumweight+",总价值为:"+maxvalue);
    }

}

程序运行结果如下:

窃贼问题求解!
窃贼背包能容纳的最大重量:8
可选物品数量:5
输入第1号物品的重量和价值:6 48
输入第2号物品的重量和价值:5 40
输入第3号物品的重量和价值:2 12
输入第4号物品的重量和价值:1 8
输入第5号物品的重量和价值:1 7

背包最大能装的重量为:8.0

第1号物品重:6.0,价值:48.0
第2号物品重:5.0,价值:40.0
第3号物品重:2.0,价值:12.0
第4号物品重:1.0,价值:8.0
第5号物品重:1.0,价值:7.0

可将以下物品装入背包,使背包的物品价值最大:
第1号物品,重量:6.0,价值:48.0
第4号物品,重量:1.0,价值:8.0
第5号物品,重量:1.0,价值:7.0

总重量为:8.0,总价值为:63.0

 

posted @ 2015-05-18 20:24  ~风轻云淡~  阅读(1167)  评论(0编辑  收藏  举报