這個寫的不錯
發現問題的起因是hdu 1712,乙個赤裸的分組揹包。所以有必要說一下這個題目。
題意:乙個學生用m天的時間複習n門課程,每門課程花費不同的天數,有不同的收穫。問如何安排這m天,使得收穫最大。
思路:可以將每一門課看成乙個分組,每門課不同天數的選擇看成是分組的物品(顯然只能有乙個選擇),物品的費用即為花費的天數,物品的價值為題中給出的收穫。該題中揹包容量最大為m。
設dp[x]為前i組物品,在揹包容量為x(即費用為x)時的最大價值。則將i從1到n進行過歷遍後(第一重迴圈),dp[m]即為所求。
在這種狀態設定中,容易想出以下兩種階段遞推方式(以下所述都為第二和第三重迴圈):
1,在同乙個揹包容量中,對不同費用的物品進行列舉比較:
for(j=max;j>=1;--j) //揹包容量
for(k=1;k<=m;++k) //不同費用的物品
2,在同一費用的物品中,對放在不同揹包容量時計算最大價值:(該方式同《揹包九講-分組揹包》中的偽**部分)
for(k=1;k<=m;++k) //不同費用的物品
for(j=max;j>=1;--j) //揹包容量
簡略分析:
1,分析第一種遞推方式的正確:
該方式即求在容量為j的揹包中,選擇哪乙個物品可以有最大價值。
看遞推方程:dp[j]=max(dp[j],dp[j-c[k]]+w[k]);(其中c[k]為k物品的費用,w[k]為價值),由於遞降列舉揹包容量,max比較中的dp[j]是由上一組物品決策所得,在這裡將被忽略。因為就算不忽略,在本組物品中dp[j]的決策依然要取決於dp[j-c[k]]+w[k]。
而同樣由於遞降列舉揹包容量(第二重迴圈),dp[j-c[k]]在本組物品中是未進行過決策的,亦即揹包容量為j-c[k]時,在本組物品中是沒有選擇任何物品的,這可以保證對dp[j]決策時,不會多選本組中的物品。
2,分析第二種遞推方式的錯誤:
該方式即求對物品k,放在所有揹包中,計算各個最大價值。
同樣是遞推方程:dp[j]=max(dp[j],dp[j-c[k]]+w[k]);(其中c[k]為k物品的費用,w[k]為價值)。能否保證dp[j-c[k]]在本組中未經決策,就成了該遞推方式對錯的關鍵。
由於揹包容量的遞降列舉在第三重迴圈,只能保證k物品不會重複選擇。對於另一k0物品,當揹包容量列舉到j-c[k]的時候,由方程可以有:dp[j-c[k]]=max(dp[j-c[k]],dp[j-c[k]-c[k0]]+w[k0],亦即dp[j-c[k]]可能在本組中的其他物品中進行過決策。
那麼這樣就可能導致在一組物品中選擇了多件物品。
///hdu 1712
#include#include#include#include#include#include#include#include#include#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long llu;
const int maxd=100+5;
const int inf = 0xfffffff;
///***************====
int val[maxd][maxd],dp[maxd];
int n,m;
void dp()
int main()
return 0;}/*
2 21 2
1 32 2
2 12 1
2 33 2 1
3 2 1
0 0*/
hdu 1712 分組揹包
分組的揹包問題 問題 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 這些物品被劃分為若干組,每組中的物品互相衝突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。演算法 這個問題變成了每組物品有若干種策略 是選擇本組的某一件,還是一件...
hdu 1712 分組揹包)
思路 這是一道簡單的分組揹包,因為每種課可以有多種選擇 花幾天時間在該課上。一旦作出選擇,就不能再選該課,就相當於有多組物品,每組內的物品互相衝突,最多只能選一件。偽碼 for 所有的組k for v v.0 for 所有的i屬於組k f v max 1 include2 const int max...
hdu1712 分組揹包
題意 有個學生要複習 n 個功課 每個功課有 m 種複習方式 每複習乙個功課就會得到一定的回報 即 滿足乙個矩陣 即 第 i 種功課需要花費 j 天並得到 v i j 的回報 問怎樣分配才能得到最大回報 理解 原以為是 01揹包 結果發現有個問題 即 如果用 1 天覆習了該功課,那麼就不能再複習該功...