C 採藥題解

2022-09-06 17:21:09 字數 2173 閱讀 3883

##演算法

裸01揹包。

##分析

這是最基礎的揹包問題,特點是:每種物品僅有一件,可以選擇放或不放。

用子問題定義狀態:即f[i][v]表示前i件物品(部分或全部)恰放入乙個容量為v的揹包可以獲得的最大價值。則其狀態轉移方程便是:f[i][v]=max。

這個方程非常重要,基本上所有跟揹包相關的問題的方程都是由它衍生出來的。所以有必要將它詳細解釋一下:「將前i件物品放入容量為v的揹包中」這個子問題,若只考慮第i件物品的策略(放或不放),那麼就可以轉化為乙個只牽扯前i-1件物品的問題。如果不放第i件物品,那麼問題就轉化為「前i-1件物品放入容量為v的揹包中」;如果放第i件物品,那麼問題就轉化為「前i-1件物品放入剩下的容量為v-w[i]的揹包中」,此時能獲得的最大價值就是f [i-1][v-w[i]]再加上通過放入第i件物品獲得的價值c[i]。

以上方法的時間和空間複雜度均為o(n\*v),其中時間複雜度基本已經不能再優化了,但空間複雜度卻可以優化到o(v)。

先考慮上面講的基本思路如何實現,肯定是有乙個主迴圈i=1..n,每次算出來二維陣列f[i][0..v]的所有值。那麼,如果只用乙個陣列f [0..v],能不能保證第i次迴圈結束後f[v]中表示的就是我們定義的狀態f[i][v]呢?f[i][v]是由f[i-1][v]和f[i-1][v-w[i]]兩個子問題遞推而來,能否保證在推f[i][v]時(也即在第i次主迴圈中推f[v]時)能夠得到f[i-1][v]和f[i-1][v-w[i]]的值呢?事實上,這要求在每次主迴圈中我們以v=v..0的逆序推f[v],這樣才能保證推f[v]時f[v-w[i]]儲存的是狀態f[i-1][v-w[i]]的值。

偽**如下:

for i=1..n

for v=v..0

f[v]=max;

其中f[v]=max相當於轉移方程f[i][v]=max,因為現在的f[v-w[i]]就相當於原來的f[i-1][v-w[i]]。如果將v的迴圈順序從上面的逆序改成順序的話,那麼則成了f[i][v]由f[i][v-w[i]]推知,與本題意不符,但它卻是另乙個重要的完全揹包問題最簡捷的解決方案,故學習只用一維陣列解01揹包問題是十分必要的。

簡單來說,設f[i][v]表示前i件物品,總重量不超過v的最優價值,則f[i][v]=max(f[i-1][v-w[i]]+c[i],f[i-1][v]) ;f[n][m]即為最優解。

##程式

###no.1:

```cpp

#include

using namespace std;

const int maxm = 201, maxn = 31;

int m, n;

int w[maxn], c[maxn];

int f[maxn][maxm];

int max(int x,int y) //求x和y最大值

int main()

```使用二維陣列儲存各子問題時方便,但當maxm較大時,如maxm=2000時不能定義二維陣列f,怎麼辦,其實可以用一維陣列。

本問題的數學模型如下:設 f[v]表示重量不超過v公斤的最大價值, 則f[v]=max ,當v>=w[i],1<=i<=n 。

###no.2:

```cpp

#include

using namespace std;

const int maxm = 2001, maxn = 31;

int m, n;

int w[maxn], c[maxn];

int f[maxm];

int main()

```###no.3:

```cpp

#include

#include

using namespace std;

int tt[200];

int vv[200];

int dp[1005][105];

int main ()

for (i = 1; i <= t; i++)

dp[i][j] = a;}}

cout << dp[t][m] << endl;

return 0;

}```

##總結

01揹包問題是最基本的揹包問題,它包含了揹包問題中設計狀態、方程的最基本思想,另外,別的型別的揹包問題往往也可以轉換成01揹包問題求解。故一定要仔細體會上面基本思路的得出方法,狀態轉移方程的意義,以及最後怎樣優化的空間複雜度。

動態規劃 採藥問題 原題 題解

這裡的採藥問題是乙個典型的0 1揹包。原題 引用open judge 總時間限制 1000ms 記憶體限制 65536kb 描述辰辰是個很有潛能 天資聰穎的孩子,他的夢想是稱為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到個到處都是草藥的...

洛谷 題解 P1048 採藥

原題鏈結p1048 採藥 題目描述 辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到乙個到處都是草藥的山洞裡對他說 孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會...

1146 採藥 詳解

回想起以前似是而非做的題,現在有必要耐下性子,總結一下!要投入熱情了。題意 有m組藥,給出採這個藥的時間time 和 這個藥的價值value。題外意 每個藥只有乙個 問在給分定時間t內如何採藥可以達到最大價值。即求規劃m組藥中的乙個子集,使在t時間內,所取子集的價值和最大。分析 歸類 0 1揹包問題...