程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> HDOJ 2159 FATE (二維背包)

HDOJ 2159 FATE (二維背包)

編輯:關於C語言

思路:根據背包9講的二維背包問題。
摘自背包九講:
問題
二維費用的背包問題是指:對於每件物品,具有兩種不同的費用;選擇這件物品必須同時付出這兩種代價;對於每種代價都有一個可付出的最大值(背包容量)。問怎樣選擇物品可以得到最大的價值。設這兩種代價分別為代價1和代價2,第i件物品所需的兩種代價分別為a[i]和b[i]。兩種代價可付出的最大值(兩種背包容量)分別為V和U。物品的價值為w[i]。
算法
費用加了一維,只需狀態也加一維即可。設f[i][v][u]表示前i件物品付出兩種代價分別為v和u時可獲得的最大價值。狀態轉移方程就是:
f[i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}
如前述方法,可以只使用二維的數組:當每件物品只可以取一次時變量v和u采用逆序的循環,當物品有如完全背包問題時采用順序的循環。當物品有如多重背包問題時拆分物品。這裡就不再給出偽代碼了,相信有了前面的基礎,你能夠自己實現出這個問題的程序。
物品總個數的限制
有時,“二維費用”的條件是以這樣一種隱含的方式給出的:最多只能取M件物品。這事實上相當於每件物品多了一種“件數”的費用,每個物品的件數費用均為1,可以付出的最大件數費用為M。換句話說,設f[v][m]表示付出費用v、最多選m件時可得到的最大價值,則根據物品的類型(01、完全、多重)用不同的方法循環更新,最後在f[0..V][0..M]范圍內尋找答案。
小結
當發現由熟悉的動態規劃題目變形得來的題目時,在原來的狀態中加一緯以滿足新的限制是一種比較通用的方法。希望你能從本講中初步體會到這種方法。


code:
#include <stdio.h> 
#include <string.h> 
int main() 

    int i = 0, j = 0, l = 0, n = 0, m = 0, k = 0, s = 0, flag = 0, a[102], b[102], dp[102][102]; 
    while(scanf("%d %d %d %d",&n, &m, &k, &s) != EOF) 
    { 
        for(i = 0; i<k; i++) 
            scanf("%d %d", &a[i], &b[i]); 
        memset(dp, 0, sizeof(dp)); 
        for(i = 0; i<k; i++) 
        { 
            for(j = b[i]; j<=m; j++)//當前要花的忍耐度 
            { 
                for(l = 1; l<=s; l++)//打怪為<=l時的經驗 
                    dp[j][l]= dp[j][l]>dp[j-b[i]][l-1]+a[i]? dp[j][l]:dp[j-b[i]][l-1]+a[i]; 
            } 
        } 
        flag = -1; 
        for(i = 1; i<=m; i++) 
        { 
            if(flag != -1) 
                break; 
            for(j = 1; j<=s; j++) 
                if(dp[i][j]>=n) 
                { 
                    flag = m-i; 
                    break; 
                } 
        } 
        if(flag == -1) 
            printf("-1\n"); 
        else 
            printf("%d\n",flag); 
    } 
    return 0; 


作者:ulquiorra0cifer

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved