1. 程式人生 > >01背包問題(動態規劃)

01背包問題(動態規劃)

最優 編號 nbsp 情況 偉大的 應該 turn 以及 main

給出背包容量C,M個物體,接下來M行分別給出物品價值V[i],以及物品重量W[i],

物品編號: 1 2 3

物品重量: 5 6 4

物品價值:20 10 12

要使得放入背包的物品價值最大化,我們知道用貪心肯定是不行的。

所以考慮動態規劃,首先定義狀態dp[i][j]為放入前i(i從小到大)個物品的最大價值,那麽i等於1的時候,放入的是物品1,這時候肯定是最優的。

接下來考慮一下j, j是當前容量;如果j < 5,就不能放,dp[1][j]=0; 那如果j > 5m就可以放了,dp[1][j] = 20;

接著 i = 2 放第二個物品的時候,求得就是 dp[2][j] 了,當 j < 5 的時候 ,同樣的dp[2][j] = 0;那當j<6的時候,是不是還是放不下第二個,只能放第一個。

那麽想一下,是不是當j>6的時候,就可以放第二個了呢?答案是可以的,但結果明顯不是最優的,想一下,dp[2][j]=20,這個20是怎麽來的呢,當然是從前一個狀態來的(註意這裏分為兩種情況)

一種是選擇第二個物品放入,另一種還是選擇前面的物品;

讓我們假設一下,j = 10 吧,這時候 dp[2][10] = max(dp[1][ 10 - w[2] ]+V[2] , dp[1][10] ); 即dp[2][10] = max(dp[1][4])+10,dp[1][10]);

結果是不是很明顯了,dp[1][4])+10是選擇了第二個,於是容量相應就減少成4,之前已經得出dp[1][4]=0,就是說選了物品2,物品1就選不了了;dp[1][10]是不選擇第二個,只選擇第一個dp[1][10]是等於20的,於是得出dp[2][10]=20;

推到這裏,我們類比往下推,就可以得出動態狀態轉移方程 ,dp[i][j] = max( dp[i-1][j - W[i] ]+ V[i] , dp[i-1][j] )

但是好像還有一些問題沒考慮完.........

看回例子:

物品編號: 1 2 3

物品重量: 5 6 4

物品價值:20 10 12

我們知道dp[1]j=20,dp[2]j的時候是多少呢?我們看到動態轉移方程並沒有考慮j<w[i]的情況,但是我們可以加進去,由於dp[2][5]我們看出來是等於5的,為什麽?因為不能選第二個,只能選第一個,所以.....dp[2][5]是不是剛好等於dp[1][5]了呢!所以當j<w[i]的時候,dp[i][j] = dp[i-1][j]就好了.

接下來上一道例題:

題目描述

辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了一個難題。醫師把他帶到一個到處都是草藥的山洞裏對他說:“孩子,這個山洞裏有一些不同的草藥,采每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裏,你可以采到一些草藥。如果你是一個聰明的孩子,你應該可以讓采到的草藥的總價值最大。”

如果你是辰辰,你能完成這個任務嗎?

輸入輸出格式

輸入格式:

第一行有222個整數T(1≤T≤1000)T(1 \le T \le 1000)T(1T1000)和M(1≤M≤100)M(1 \le M \le 100)M(1M100),用一個空格隔開,TTT代表總共能夠用來采藥的時間,MMM代表山洞裏的草藥的數目。
接下來的MMM行每行包括兩個在111到100100100之間(包括111和100100100)的整數,分別表示采摘某株草藥的時間和這株草藥的價值。

70 3

71 100

69 1

1 2

輸出格式:

111個整數,表示在規定的時間內可以采到的草藥的最大總價值。

3

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=100+10;
 6 int w[maxn],val[maxn];
 7 int dp[maxn][1005];
 8 
 9 int main(){
10     int t,m;
11     cin>>t>>m;
12     for( int i=1; i<=m; i++ ){
13         cin>>w[i]>>val[i];
14     }
15     for( int i=1; i<=m; i++ ){
16         for( int j=t; j>=0; j-- ){
17             if(j>=w[i]){
18                 dp[i][j]=max(dp[i-1][j-w[i]]+val[i],dp[i-1][j]);
19             }
20             else{
21                 dp[i][j]=dp[i-1][j];
22             }
23         }
24     }
25     cout<<dp[m][t];
26     return 0;
27 }

01背包問題(動態規劃)