背包问题

介绍

学习动态规划算法的经典例题。
动态规划算法一般有3个特征
1、最优化原理:最优解所包含的子问题的解也是最优的。
2、无后效性:就是后面问题的解决不引起前面问题解的变动,或者说不影响前面问题的解。
3、重叠子问题:就是说各子问题之间互相关联,即,以后问题的解可能会重复用到前面子问题的解。
另外,动态规划的输出往往依赖于链表的回溯。

思路

现在要达到的目的就是要求出在当前现有商品和背包容量的条件下如果才能使价值最高。
1、如果背包除了能装下当前物品外还有剩余容量的话,那么可以在刨去当前物品的情况下去找当背包容量等于这个剩余容量的值的时候的最优解。如果当前物品的价值+剩余容量的最优解优于刨去当前物品的当前背包容量的最优解的时候,那么当前物品在当前背包容量条件下的更优解就找到了。否则保持原样不变。
2、如果背包刚好能装下当前物品,那就直接跟刨去当前物品在当前背包容量条件下的最优解进行比较。如果优于这个最优解就更新在当前物品当前背包容量的前提下的最优解,否则保持不变。
3、根本装不下,于是直接保持原来最优解不变。

用法

package com.company;

public class Main {

    public static void main(String[] args) {
    // write your code here
        Good[] goodsArray = {
                new Good("水",10,3),
                new Good("书",3,1),
                new Good("食物",9,2),
                new Good("夹克",5,2),
                new Good("相机",6,1)
        };
        Good[] goodsArray0 = {
                new Good("吉他",1500,1),
                new Good("音响",3000,4),
                new Good("笔记本电脑",2000,3)
        };
        Bag.bagSolution(goodsArray,6);
    }
}

输出

解集:
0   0   10  10  10  10  
3   3   10  13  13  13  
3   9   12  13  19  22  
3   9   12  14  19  22  
6   9   15  18  20  25  
背包中物品价值最高为:25
相机  价值:6    重量:1
食物  价值:9    重量:2
水   价值:10   重量:3

Process finished with exit code 0

实现

package com.company;

public class Bag {
    /**
     * 动态规划算法最著名的背包问题
     * 每次装背包时只需要知道当背包重量排除某物品时
     * 加上余下空余重量的最优解才能得到当前的解。
     * 如果当前的解比已经得到同重量背包解更优就更新改重量背包的最优解。
     * 比较麻烦的是列举出背包中有哪些物品。
     * 也是用单链表,如果某单元格并不添加新物品则指针指向上面的单元格。
     * 否则指向左上边对应的单元格
     * 但是第一行要特殊处理。
     * @param goodsArray
     * @param bagSize
     */
    static public void bagSolution(Good[] goodsArray,int bagSize) {
        if (bagSize <= 0 || goodsArray.length <= 0) {
            System.out.println("无解");
            return;
        }
        BestSolution[][] answerArray = new BestSolution[goodsArray.length][bagSize];
        for (int counter = 0;counter < goodsArray.length;counter++)
            for (int counter0 = 0;counter0 < bagSize;counter0++)
                answerArray[counter][counter0] = new BestSolution();
        for (int counter = 0;counter < goodsArray.length;counter++) {
            for (int counter0 = 0;counter0 < bagSize;counter0++) {
                int remainingWeight = counter0 - goodsArray[counter].getWeight() + 1;
                if (remainingWeight > 0) {
                    //有剩余空间
                    if (counter - 1 >= 0) {
                        //如果不是第一行
                        if (answerArray[counter - 1][remainingWeight - 1].getMaxValue() + goodsArray[counter].getValue() > answerArray[counter - 1][counter0].getMaxValue()) {
                            answerArray[counter][counter0].goodPointer = goodsArray[counter];
                            answerArray[counter][counter0].prePointer = answerArray[counter - 1][remainingWeight - 1];
                            answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][remainingWeight - 1].getMaxValue() + goodsArray[counter].getValue());
                        } else {
                            answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
                            answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][counter0].getMaxValue());
                        }
                    } else {
                        //是第一行
                        answerArray[counter][counter0].goodPointer = goodsArray[counter];
                        answerArray[counter][counter0].setMaxValue(goodsArray[counter].getValue());
                    }
                } else if (remainingWeight == 0){
                    //刚好装下
                    if (counter - 1 >= 0) {
                        if (goodsArray[counter].getValue() > answerArray[counter - 1][counter0].getMaxValue()) {
                            answerArray[counter][counter0].goodPointer = goodsArray[counter];
                            answerArray[counter][counter0].setMaxValue(goodsArray[counter].getValue());
                        } else {
                            answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
                            answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][counter0].getMaxValue());
                        }
                    } else {
                        answerArray[counter][counter0].goodPointer = goodsArray[counter];
                        answerArray[counter][counter0].setMaxValue(goodsArray[counter].getValue());
                    }
                } else {
                    //根本装不下
                    if (counter - 1 >= 0) {
                        answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
                        answerArray[counter][counter0].setMaxValue(answerArray[counter - 1][counter0].getMaxValue());
                    }
                }
            }
        }
        System.out.println("解集:");
        for (int counter = 0;counter < goodsArray.length;counter++) {
            for (int counter0 = 0;counter0 < bagSize;counter0++) {
                System.out.print(answerArray[counter][counter0].getMaxValue() + "\t");
            }
            System.out.println();
        }
        System.out.println("背包中物品价值最高为:" + answerArray[goodsArray.length - 1][bagSize - 1].getMaxValue());
        BestSolution headPointer = answerArray[goodsArray.length - 1][bagSize - 1];
        while (headPointer != null) {
            if (headPointer.goodPointer != null)
                System.out.println(headPointer.goodPointer.getGoodName() + "\t价值:" + headPointer.goodPointer.getValue() + "\t重量:" + headPointer.goodPointer.getWeight());
            headPointer = headPointer.prePointer;
        }
    }
}

package com.company;

public class BestSolution {
    public Good goodPointer = null;
    public BestSolution prePointer = null;
    private int maxValue = 0;

    public BestSolution() {
    }

    public int getMaxValue() {
        return maxValue;
    }

    public void setMaxValue(int maxValue) {
        this.maxValue = maxValue;
    }
}

package com.company;

public class Good {
    private String goodName;
    private int value;
    private int weight;
    public Good nextPointer = null;

    public Good(String goodName, int value, int weight) {
        this.goodName = goodName;
        this.value = value;
        this.weight = weight;
    }

    public String getGoodName() {
        return goodName;
    }

    public int getValue() {
        return value;
    }

    public int getWeight() {
        return weight;
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容