訓練第三週之dp 揹包訓練

2021-07-15 21:24:05 字數 3669 閱讀 2666

題目:有n件物品和乙個容量為v的揹包。第i件物品的費用是w[i],價值是v[i]。求解將哪些物品裝入揹包可使價值總和最大。

分析:每種物品都有兩種狀態,放或者不放,那麼只要比較放所得的價值與不放揹包內原有價值就能得到最大價值

二維陣列:f[i][j]表示前i件物品放入容量為j的揹包可以獲得的最大價值

for i=1...n

for j=0...c

if j>=w[i]

dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

//不放價值為dp[i][j]=dp[i-1][j],前i-1件物品放入容量為j的揹包所獲價值

//放則dp[i][j]=dp[i-1][j-w[i]]+v[i],前i-1件物品放入容量為j-w[i]的揹包的最大價值加上第i件物品的價值v[i]

一維陣列:f[j]表示容量為j的揹包可以獲得的最大價值
for i=1..n

for j=v..0

/*倒序是為了保證每件物品只選一次,保證在考慮「選入第i件物品」這件策略時,依據的是乙個絕無已經選入第i件物品的子結果f[j-w[i]],所以才逆推過去的*/

思路:每種物品只有放和不放兩種狀態,不放則揹包內價值為f[i-1][j],放了則為f[i-1][j-w[i]]+v[i],意思是前i-1件物品放入容量為j-w[i]的揹包的最大價值加上第i件物品的價值v[i],取兩者最大值為最大價值

**:

#include

#include

#include

#include

using

namespace

std;

int v[1005],w[1005];//v為價值,w為體積

int dp[1005][1005];

int main()

else

dp[i][j]=dp[i-1][j];

// printf("%d ",dp[i][j]);

}//printf("\n");

}printf("%d\n",dp[n][v]);}}

思路:這個題目稍有不同,顯然當餘額為5的時候去買那最大價值的物品才能使卡內餘額最少,我們不妨直接先拿出5塊,也去掉最大價值的物品,這樣就是簡單的01揹包了,這裡我採用了一維陣列,f[j]為容量為j的揹包所能放入的最大價值

**:

#include

#include

#include

#include

using

namespace

std;

int price[1005],f[1005];

int main()

sort(price,price+n+1);//排序是為了找出最大價值的物品

max=price[n];

for(i=1;ifor(j=m-5;j>=price[i];j--)//j=m-5是最後留下5塊買那個最大價值的物品

//printf("%d\n",f[j]);

}printf("%d\n",m-max-f[m-5]);}}

題目:有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的費用是w[i],價值是v[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

偽**:

for i=1..n

for j=0..v/*與01揹包相比只是j的順序不同而已,是因為完全揹包的特點恰是每種物品可選無限件,所以在考慮「加選一件第i種物品」這種策略時,正需要乙個可能已選入第i種物品的子結果f[j-w[i]],所以順推過去*/

f[j]=max

#include

#include

#include

#include

using

namespace

std;

int p[50005],w[10005];

int f[10005];

int main()

}if(f[g-e]>=2e9)

printf("this is impossible.\n");

else

printf("the minimum amount of money in the piggy-bank is %d.\n",f[g-e]);}}

題目:有n種物品和乙個容量為v的揹包。第i種物品最多有c[i]件可用,每件費用是w[i],價值是v[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

分析:這個就相當於01揹包和完全揹包的綜合,不止取一件,也取不了任意件。所以我們可以用二進位制思想將其轉化為01揹包問題

方法:將第i件物品用二進位制轉化為若干件物品,每件物品有乙個係數,係數為1,2,4,…,2^(k-1),c[i]-2^k+1,且k是滿足c[i]-2^k+1>0的最大整數,因為2^k-1為前k-1的和。如13,轉化為1,2,4,6,那麼就把第i件分成了k件,物品的費用和價值均是原來的費用和價值乘以這個係數

核心**:

for(i=1;i<=m;i++)//m為物品種類

for(j=n;j>=p[i]*(c[i]-k+1);j--)//若干件中最後一件的係數為c[i]-k+1

f[j]=max(f[j],f[j-p[i]*(c[i]-k+1)]+w[i]*(c[i]-k+1));

//printf("%d\n",f[j]);

}

**:
#include

#include

#include

#include

using namespace std;

int p[105],w[105],c[105];

int f[105];

int main()

for(j=n;j>=p[i]*(c[i]-k+1);j--)

f[j]=max(f[j],f[j-p[i]*(c[i]-k+1)]+w[i]*(c[i]-k+1));

//printf("%d\n",f[j]);

}while(n--)

if(f[n+1])}}

**:
#include

#include

#include

#include

using namespace std;

int c[10],s=1;

int f[200005];

int main()

if(flag)

else

//printf("\n");

for(j=v;j>=i*(c[i]-k+1);j--)

}if(f[v]==v)

else}}

else

break;

}while(s++);

return

0;}

訓練第三週之dp習題

個人感覺做dp題目就是求什麼就設什麼,dp i 陣列就是所求,然後找出子問題,寫出狀態轉移方程就差不多出來了這個題目思路很簡單,就是求子串最大和。但是就是要記錄開頭結尾還有如果相等記錄第乙個,讓我吃盡了苦頭。include include include include using namespac...

第三週訓練總結(補充貪心)

例題 有n頭牛,分別給出可以承受的光照範圍,有m瓶防曬霜,可以將溫度控制在k度,但只有有限瓶,求最多可以讓多少頭牛曬陽光 先按牛所承受的溫度公升序排序,防曬霜公升序排序 如果防曬霜大於所承受最低溫,放入佇列 priority queue,greater q 再一次比較放入佇列的防曬霜,對應的防曬霜有...

第三週 1 3揹包問題2

n個物品,每個物品有乙個體積v和價值w。現在你要回答,把乙個物品丟棄後,剩下的物品裝進乙個大小為v的揹包裡能得到的最大價值是多少。輸入的第一行包含乙個正整數n n 5000 接下來n行,每行包含兩個正整數v和w v,w 5000 分別表示乙個物品的體積和價值。接下來一行包含乙個正整數q q 5000...