動態規划:分組背包和有依賴的背包


我們先來看分組背包問題

有N件物品和一個容量為V的背包,第i件物品的重量為c[i],價值為w[i],這些物品被划分成了若干組,每組中的物品互相沖突,最多選一件

問將哪些物品放入背包中可以使背包獲得最大的價值

我們用f[k][v]表示前k種物品花費費用v所能取得的最大價值

給出狀態轉移方程:

f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i屬於第k組}

可以看出,這個問題還是很顯然的,下面給出完整的實現:

在實現的時候稍微皮了一下~~

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring> 
 4 using namespace std;
 5 const int maxn=105;
 6 const int maxv=105;
 7 const int maxt=15;
 8 int N,V,T;
 9 int v[maxn],w[maxn];
10 int f[maxv];
11 int a[maxt][maxn];
12 int main()
13 {
14     cin>>V>>N>>T; 
15     for(int i=1;i<=N;i++)
16     {
17         int p;
18         cin>>v[i]>>w[i]>>p;
19         a[p][++a[p][0]]=i;  //存每一組的所有物品的編號 
20         //a[p][0]表示第p組一共有幾個物品 
21     }
22     for(int i=1;i<=T;i++)
23     for(int j=V;j>=0;j--)
24     for(int k=1;k<=a[i][0];k++)
25     if(j-v[a[i][k]]>=0)
26         f[j]=max(f[j],f[j-v[a[i][k]]]+w[a[i][k]]);
27     cout<<f[V]<<endl;
28     return 0;
29 }
30  

下面介紹有依賴的背包,參考題目為NOIP金明的預算方案

在這種背包中引入了主件和附件的概念,只有放了主件之后才能放與之相關聯的附件

最開始我是用生成組合的形式來解決這個問題的

即以主件為基准,和每一種附件的情況進行捆綁,再放01背包

但是我們有更皮的解決方法

將每一個主件對應的附件集合先做一次01背包

下面給出一道例題來實現這個方法,本例題中的主件是沒有價值的,如果主件有價值可以在這個的基礎上進行簡單的修改

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=55;
 6 const int maxv=100005;
 7 int tmp[maxv];
 8 int f[maxn][maxv];
 9 int N,V;  //主件的數量,背包的容量 
10 int main()
11 {
12     while(cin>>N>>V)
13     {
14         memset(f,0,sizeof(f));
15         for(int i=1;i<=N;i++)
16         {
17             memset(tmp,-1,sizeof(tmp));
18             int p,m;  //主件的費用,附件的數量 
19             cin>>p>>m;
20             for(int j=p;j<=V;j++)
21                 tmp[j]=f[i-1][j-p];
22             int v,w;
23             for(int j=1;j<=m;j++)
24             {
25                 cin>>v>>w;  //每一個附件的重量和價值 
26                 for(int k=V;k>=v;k--)
27                 if(tmp[k-v]!=-1)
28                     tmp[k]=max(tmp[k],tmp[k-v]+w);
29             }
30             for(int j=V;j>=0;j--)
31                 f[i][j]=max(tmp[j],f[i-1][j]);
32         }
33         cout<<f[N][V]<<endl;
34     }
35     return 0;
36 }

另外,如果附件是另一件物品的主件,就是樹形動態規划了,參考選課那道題目,將在以后進行介紹


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM