有n件物品,每件物品的重量為w[i],價值為v[i]。現有乙個容量為c的揹包,問如何選取物品放入揹包,使得揹包內物品的總價值最大。其中每種物品都只有一件。
用dp[i][j]表示有前i件物品、揹包容量為j時揹包所能放下物品的最大價值。
對每件物品進行決策,不選(0)或是選(1)。
狀態轉移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]
#includeusingnamespace
std;
#define max_capaticy 100
#define max_quantity 100
int w[max_quantity+2];///
物品重量
int v[max_quantity+2];///
物品價值
int dp[max_quantity+2][max_capaticy+2
];int c,n;///
揹包容量和物品數量
void
print()
else
}}int
main()
for(int i=1;i<=n;++i)}}
cout
//print();
///輸出被選擇的物品
}
return0;
}
根據狀態轉移方程可以看出dp[i][j]只與dp[i-1]行(上一行)有關
所以可以將二維陣列優化成 dp[max_quantity+2][2] 只有兩行的滾動陣列
如果改變內層迴圈的順序,從後往前推,j較大時dp[j]發生改變不會影響到j較小時dp[j]的計算,則可以用一維陣列來實現
#includeusingnamespace
std;
#define max_capaticy 100
#define max_quantity 100
int w[max_quantity+2];///
物品重量
int v[max_quantity+2];///
物品價值
int dp[max_quantity+2];///
使用一維陣列
int c,n;///
揹包容量和物品數量
intmain()
for(int i=1;i<=n;++i)
}cout
}return0;
}
有n種物品,每件物品的重量為w[i],價值為v[i]。現有乙個容量為c的揹包,問如何選取物品放入揹包,使得揹包內物品的總價值最大。其中每種物品都有無限件。
完全揹包與0/1揹包的唯一不同之處就在於完全揹包問題中每種物品有無限件。
同樣用dp[i][j]表示有前i件物品、揹包容量為j時揹包所能放下物品的最大價值。
對每種物品進行決策,不選(0)或是選(至少一件)
狀態轉移方程:dp[i][j]=max(dp[i-1][j],dp[i][j-k*w[i]]+k*v[i])
#includeusingnamespace
std;
#define max_capaticy 100
#define max_quantity 100
int w[max_quantity+2];///
物品重量
int v[max_quantity+2];///
物品價值
int dp[max_quantity+2][max_capaticy+2
];int c,n;///
揹包容量和物品種數
intmain()
for(int i=1;i<=n;++i)}}
}cout
}return0;
}
同樣也可以用一維陣列來實現,不但大大優化了空間複雜度,也優化了時間複雜度
完全揹包的一維陣列實現迴圈是順序的,與0/1揹包不同,能取無限件同類物品的完全揹包正好需要在前面選擇過的基礎上進行選擇
#includeusingnamespace
std;
#define max_capaticy 100
#define max_quantity 100
int w[max_quantity+2];///
物品重量
int v[max_quantity+2];///
物品價值
int dp[max_quantity+2];///
使用一維陣列
int c,n;///
揹包容量和物品數量
intmain()
for(int i=1;i<=n;++i)
}cout
}return0;
}
有n種物品,每件物品的重量為w[i],價值為v[i]。現有乙個容量為c的揹包,問如何選取物品放入揹包,使得揹包內物品的總價值最大。其中每種物品都有m[i]件。
多重揹包與完全揹包的思路差不多
用dp[i][j]表示有前i件物品、揹包容量為j時揹包所能放下物品的最大價值。
對每種物品進行決策,不選(0)或是選(至少一件)
狀態轉移方程:dp[i][j]=max(dp[i-1][j],dp[i][j-k*w[i]]+k*v[i])
僅僅是這裡k多了乙個限制條件 k<=m[i]
#includeusingnamespace
std;
#define max_capaticy 100
#define max_quantity 100
int w[max_quantity+2];///
物品重量
int v[max_quantity+2];///
物品價值
int m[max_quantity+2];///
第i種物品的件數
int dp[max_quantity+2][max_capaticy+2
];int c,n;///
揹包容量和物品種數
intmain()
for(int i=1;i<=n;++i)}}
}cout
}return0;
}
同樣可優化為一維陣列的寫法
當某種物品總重量超過揹包容量 m[i]*w[i]>c 時,可以當成完全揹包來計算
否則,轉換成0/1揹包求解
為進一步優化時間複雜度 這裡還可以用2進製想法
把一種物品分成若干份,將第i種物品分成若干件物品,其中每件物品有乙個係數,這件物品的費用和價值均是原來的費用和價值乘以這個係數。使這些係數分別為1,2,4,...,2^(k-1),m[i]-2^k+1,且k是滿足n[i]-2^k+1>0的最大整數。這樣1-m[i]的所有數都可以被表示出來
#includeusingnamespace
std;
#define max_capaticy 100
#define max_quantity 100
int w[max_quantity+2];///
物品重量
int v[max_quantity+2];///
物品價值
int m[max_quantity+2];///
第i種物品的件數
int dp[max_quantity+2];///
使用一維陣列
int c,n;///
揹包容量和物品數量
intmain()
for(int i=1;i<=n;++i)
}else
dp[j]=max(dp[j],dp[j-num*w[i]]+num*v[i]);}}
}cout
}return0;
}
揹包問題1
有n個魔法石,重量分別為w1,w2,w3 wn,有乙個可裝重量為s的揹包,從n件魔法石中取若干件,使得放入揹包的重量之和剛好為s,求放的方法,若不存在該種情況則輸出failed。輸入樣例 10 s 5 n 重量 1 2 3 4 5 輸出樣例 1 4 5 遞迴,即乙個乙個將物品放入揹包內試一下,設函式...
揹包問題1
做了兩道揹包問題,迷迷糊糊也算是弄懂了一些揹包的模型。poj1837 這個題主要是建立揹包模型bi比較難,當時沒有想到第二維可以是平衡狀態,看到網上大佬的提示才想到,如下 include include include includeusing namespace std int dp 25 150...
揹包問題 1 揹包的引入
上篇文章我考慮的是可以找零的方式有幾種,是運用搜尋解決的,但是如果我們要解決的是優化問題,就是說最小要多少硬幣呢?題目的位址是 其實他是乙個揹包問題,所以我準備重學一下。最近做硬幣找零問題,它實際是個揹包問題,很多知識掌握的不紮實。這裡重新總結一下,老規矩,還是靠題目驅動,下面所有題目都給了鏈結 大...