背包問題

image.png

image.png

來源

以下是自己寫的

import java.util.Scanner;
public class test{
    public static void main(String[] args){
        int totalPersons = 10;
        int[] value = {500, 200, 300, 350, 400};
        int[] persons = {5, 3, 4, 3, 5};
      //這里儲存整個maxMatri雀彼,實際上只用到了前一行,所以和上面的代碼相比浪費空間了转绷。
        int[][] maxMatri = new int[value.length][totalPersons + 1];

        for(int i = persons[0]; i < totalPersons + 1; ++i){
                maxMatri[0][i] = value[0];
        }

        for(int i = 1; i < value.length; ++i){

            for( int j = 1; j < totalPersons + 1; ++j){
                maxMatri[i][j] =j - persons[i] >= 0 ?  Math.max(maxMatri[i - 1][j], maxMatri[i - 1][j - persons[i]] + value[i]) : maxMatri[i -1][j];
            }
        }
        
        System.out.println(maxMatri[maxMatri.length - 1][maxMatri[0].length - 1]);
    }

}
import java.util.Scanner;
public class test{
    /**
     * more concise
     */
    public static void main(String[] args){
        int totalPersons = 10;
        int[] value = {500, 200, 300, 350, 400};
        int[] persons = {5, 3, 4, 3, 5};
        int[] maxProfit = new int[totalPersons + 1];

        for(int i = 0; i < value.length; ++i){

            for( int j = totalPersons; j >= persons[i]; --j){
                if( i == 0){
                    maxProfit[j] = value[i];
                    continue;
                }
                maxProfit[j] = Math.max(maxProfit[j], maxProfit[j - persons[i]] + value[i]);
                if( i == value.length -1 && j == totalPersons)
                    break;
            }

        }
        
        System.out.println(maxProfit[totalPersons]);
    }

}

01背包

也可以這么解

import java.util.Scanner;
public class test{
    public static void main(String[] args){
        //weight
        int [] w = {2,2,6,5,4};
        //value
        int [] v = {6,3,5,4,6};
        System.out.println(package01(w, v, 10));
    }

    private static int package01(int w[], int v[], int totalW){
        /**
         * This method wastes memory
         */
        // int[] preF = new int[totalW + 1];
        // int[] f = new int[totalW + 1];
        // for(int i = 0; i < w.length; ++i){
        //     for(int j = 0; j < totalW + 1; ++j){
        //         if(j == 0){
        //             preF[j] = w[0];
        //             continue;
        //         }
        //         f[j] =  j - w[i] > 0? Math.max(preF[j], preF[j - w[i]] + v[i]) : preF[j];
        //     }
        //     for(int j = 1; j < totalW + 1; ++j){
        //         preF[j] = f[j];
        //     }
        // }
        int [] maxp = new int [totalW + 1];

        for(int i = 0; i < w.length; ++i){
            for(int j = totalW; j >= w[i]; --j){
                maxp[j] = Math.max(maxp[j], maxp[j - w[i]] + v[i]);
            }
        }

        return maxp[totalW];
    }

}

完全背包

只需修改為

        for(int i = 0; i < w.length; ++i){
            for(int j = w[i]; j < totalW+1; ++j){
                maxp[j] = Math.max(maxp[j], maxp[j - w[i]] + v[i]);
            }
        }

多重背包

題目:輸入數(shù)據(jù)首先包含一個正整數(shù)C,表示有C組測試用例硼啤,每組測試用例的第一行是兩個整數(shù)n和m(1<=n<=100, 1<=m<=100),分別表示經(jīng)費的金額和大米的種類议经,然后是m行數(shù)據(jù),每行包含3個數(shù)p丙曙,h和c(1<=p<=20,1<=h<=200,1<=c<=20)爸业,分別表示每袋的價格、每袋的重量以及對應(yīng)種類大米的袋數(shù)亏镰。對于每組測試數(shù)據(jù)扯旷,請輸出能夠購買大米的最多重量,你可以假設(shè)經(jīng)費買不光所有的大米索抓,并且經(jīng)費你可以不用完钧忽。每個實例的輸出占一行毯炮。

定理:一個正整數(shù)n可以被分解成1,2,4,…,2(k-1),n-2k+1(k是滿足n-2k+1>0的最大整數(shù))的形式,且1~n之內(nèi)的所有整數(shù)均可以唯一表示成1,2,4,…,2(k-1),n-2^k+1中某幾個數(shù)的和的形式.
證明如下:

(1) 數(shù)列1,2,4,…,2(k-1),n-2k+1中所有元素的和為n耸黑,所以若干元素的和的范圍為:[1, n]桃煎;
(2)如果正整數(shù)t<= 2^k – 1,則t一定能用1,2,4,…,2(k-1)中某幾個數(shù)的和表示,這個很容易證明:我們把t的二進(jìn)制表示寫出來大刊,很明顯为迈,t可以表示成n=a0*20+a12^1+…+ak2^(k-1),其中ak=0或者1缺菌,表示t的第ak位二進(jìn)制數(shù)為0或者1.
(3)如果t>=2k,設(shè)s=n-2k+1葫辐,則t-s<=2k-1,因而t-s可以表示成1,2,4,…,2(k-1)中某幾個數(shù)的和的形式伴郁,進(jìn)而t可以表示成1,2,4,…,2^(k-1)耿战,s中某幾個數(shù)的和(加數(shù)中一定含有s)的形式。
(證畢:父怠)

import java.util.ArrayList;
import java.util.Scanner;
public class test{
    /**
     * more concise
     */
    public static void main(String[] args){
        int money = 8;
        int[] value = {2,4};
        int[] weight = {100, 100};
        int[] amount = {4, 2};
        
        System.out.println(multiplePackage(money, value, weight, amount));
    }

    private static int multiplePackage(int money, int[] value, int[] weight, int[] amount){
        int[] dp = new int[money + 1];

        //關(guān)鍵
        ArrayList<Integer> valueList = new ArrayList<>();
        ArrayList<Integer> weightList = new ArrayList<>();
        for(int i = 0; i < value.length; ++i){
            for(int j = 1; j < amount[i]; j <<= 1){
                valueList.add(value[i] * j);
                weightList.add(weight[i] * j);
                amount[i] -= j;
            }
            if(amount[i] > 0){
                valueList.add(amount[i] * value[i]);
                weightList.add(amount[i] * weight[i]);
            }
        }

      //還是01背包的解法
        for(int i = 0; i < valueList.size(); ++i){
            for(int j = money; j >= valueList.get(i); --j){
                if( dp[j] < dp[j - valueList.get(i)] + weightList.get(i)){
                        dp[j] = dp[j - valueList.get(i)] + weightList.get(i);
                }
            }
        }

        return dp[money];
    }

}

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末剂陡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狐胎,更是在濱河造成了極大的恐慌鸭栖,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顽爹,死亡現(xiàn)場離奇詭異纤泵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)镜粤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玻褪,“玉大人肉渴,你說我怎么就攤上這事〈洌” “怎么了同规?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窟社。 經(jīng)常有香客問我券勺,道長,這世上最難降的妖魔是什么灿里? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任关炼,我火速辦了婚禮,結(jié)果婚禮上匣吊,老公的妹妹穿的比我還像新娘儒拂。我一直安慰自己寸潦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布社痛。 她就那樣靜靜地躺著见转,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蒜哀。 梳的紋絲不亂的頭發(fā)上斩箫,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機(jī)與錄音撵儿,去河邊找鬼校焦。 笑死,一個胖子當(dāng)著我的面吹牛统倒,可吹牛的內(nèi)容都是我干的寨典。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼房匆,長吁一口氣:“原來是場噩夢啊……” “哼耸成!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浴鸿,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤井氢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后岳链,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體花竞,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年掸哑,在試婚紗的時候發(fā)現(xiàn)自己被綠了约急。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡苗分,死狀恐怖厌蔽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摔癣,我是刑警寧澤奴饮,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站择浊,受9級特大地震影響戴卜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜琢岩,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一投剥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粘捎,春花似錦薇缅、人聲如沸危彩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汤徽。三九已至,卻和暖如春灸撰,著一層夾襖步出監(jiān)牢的瞬間谒府,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工浮毯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留完疫,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓债蓝,卻偏偏與公主長得像壳鹤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饰迹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案芳誓? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,760評論 1 92
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,305評論 25 707
  • 1锹淌,遇到心儀的女孩,想要她的聯(lián)系方式赠制,結(jié)果東拉西扯聊了半天赂摆,遲遲不知道怎么切入正題,怎么辦钟些? 你:blablabl...
    苜蓿巷三號閱讀 1,228評論 0 3
  • 終究是變成了張皇失措的鬼 是你么 牽縱我的 孤寂桀驁的魂 像是被毀掉的木偶 無助恐慌 顫抖的眼神 與我一般 同...
    荼四閱讀 252評論 0 2
  • 文章格式參考來自:http://www.reibang.com/p/7c14d8c4ede5現(xiàn)在iPhone X也...
    阿小大人閱讀 934評論 0 1