窃贼问题

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

有一个窃贼带着一个背包去偷东西,房屋中共有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
时间: 2024-10-12 20:50:36

窃贼问题的相关文章

LeetCode OJ:House Robber II(房屋窃贼II)

After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place arearranged in a circle. That means the first house is the neighbor of

关窗锁门严防数据窃贼

公司老总将一些重要文档交给秘书小华,告诉他要妥善保管,不要让无关人员接触.小华自然不敢怠慢,不过又不能始终抱着电脑不放,看来还得另想妙策.经过一番思考,小华认为只要将电脑可能的泄密途径全部封闭,数据自然可以高枕无忧. 技术部的好友小李给小华推荐了Port Locker这款软件,这是他以前在看危险漫步的博客上看到的方法.这样,终于让小华找到了解决问题的良策.Port Locker可以彻底封锁USB端口.IEEE 1394端口.网卡端口.光驱端口.打印机端口.红外端口等电脑与外界连接的通道,犹如将房

LeetCode OJ:House Robber(住宅窃贼)

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will autom

用itertools.product简化嵌套for循环

今天这一题叫做"偷瞄到的密码": 警察跟踪一名窃贼来到了一个仓库门前.仓库的密码锁盘如下: 1 2 3 4 5 6 7 8 9 0 窃贼输入密码后进了门.警察"觉得"自己看到了密码比如1357,但是也有可能是相邻的数字(相邻仅包括正上下左右,不包括对角线),比如第一位不是1,而是相邻的4和2(不包括5). 可能的密码是哪些组合呢? 这道题目可以抽象成: 1. 0-9各自都对应了一组相邻数字 现给定一个数字串: 2. 对数字串中的每个数字,找到对应的相邻数组 3. 计

通过使用OpenVPN来构建一个VPN

首先我们需要简单熟悉一下OpenVPN和VPN概念,方便我们在使用OpenVPN构建VPN时的操作~  VPN概述 VPN,即虚拟专用网络,其功能是:在公用网络上建立专用网络,进行加密通讯.在企业网络中有广泛应用.VPN网关通过对数据包的加密和数据包目标地址的转换实现远程访问.VPN有多种分类方式,主要是按协议进行分类.VPN可通过服务器.硬件.软件等多种方式实现. VPN属于远程访问技术,简单地说就是利用公用网络架设专用网络.例如某公司员工出差到外地,他想访问企业内网的服务器资源,这种访问就属

[转]100个经典C语言程序(益智类问题)

目录: 1.绘制余弦曲线 2.绘制余弦曲线和直线 3.绘制圆 4.歌星大奖赛 5.求最大数 6.高次方数的尾数 8.借书方案知多少 9.杨辉三角形 10.数制转换 11.打鱼还是晒网 12.抓交通肇事犯 13.该存多少钱 14.怎样存钱利最大 15.捕鱼和分鱼 16.出售金鱼 1.7 分数四则运算 17.平分七筐鱼 18.有限5位数 19. 8 除不尽的数 21.4位反序数 22.求车速 23.阿姆斯特朗数 24.完全数 26.亲密数 27.自守数 28.回文数 29.求具有abcd=(ab+c

Exchange Server 2013就地存档

9.1就地存档 就地存档有助于重新获得对组织邮件数据的控制,而无需个人存储 (.pst) 文件,并且允许用户在可通过 Microsoft Outlook 2010及更高版本和 Microsoft Office Outlook Web App 访问的"存档邮箱"中存储邮件. 在 Microsoft ExchangeServer 2013 中,就地存档向用户提供了一个存储历史邮件数据的备用存储位置.就位存档是对邮箱用户启用的其他邮箱(称为存档邮箱).Outlook 2007 及更高版本和

东皇车业品牌运营中心欧巴

东皇远程遥控电动车,以"非锁防盗"为标志的智能化安全监控系统,电动车不用锁,窃贼再无藏身之处,其铜墙铁壁般的防盗系统,不仅是电动车技术的重大创新,也开辟了电动自行车定位追踪的先河. 东皇安全监控系统,实现与车主手机联动,车主可以通过手机或互联网,实时查询车辆位置.行驶轨迹.即使偷盗者将电动车开走,依托GPS卫星GSM基站双模定位,能在全国范围内精确锁定失窃车辆的位置,精确范围可在5米以内:并且还可通过手机监控失窃车辆运行轨迹,大幅提升警方破案的效率和成功率. 鸿蒙紫玉_第九十五章 上仙

东皇车业品牌运营中心脱北者

东皇远程遥控电动车,以"非锁防盗"为标志的智能化安全监控系统,电动车不用锁,窃贼再无藏身之处,其铜墙铁壁般的防盗系统,不仅是电动车技术的重大创新,也开辟了电动自行车定位追踪的先河. 血雾四溅几名汉子睁大着双眼双手捂住脖劲,想发出警报信号但被咕噜,咕噜 .的冒血声所代替.每名汉子的脖子直接被三凌军刺穿透而过,没有丝毫的反抗当场死亡. "报告银狐,没有什么事,刚才六号太敏感了,以为敌人偷袭." 哈哈,你个无耻的家伙,要是给上面银狐大人,可有够你受的."同样站在