動態規劃--揹包問題(01揹包、徹底揹包、多重揹包)

01揹包(ZeroOnePack):
有N件物品和一個容量爲V的揹包。(每種物品均只有一件)第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使價值總和最大。
徹底揹包(CompletePack):
有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。第i種物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使這些物品的費用總和不超過揹包容量,且價值總和最大。
多重揹包(MultiplePack):
有N種物品和一個容量爲V的揹包。第i種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使這些物品的費用總和不超過揹包容量,且價值總和最大。
異同點:
比較三個題目,會發現不一樣點在於每種揹包的數量,01揹包是每種只有一件,徹底揹包是每種無限件,而多重揹包是每種有限件。

01揹包:max {f[ i-1 ][ v ], f[ i ][ v - vi ] + wi } 時間 O(VN) 空間 O(VN) -->O(V)node

for(i=1; i<=n; i++)ios

for(j=v; j>=v[ i ]; j-- )//逆序保持次循環內的值和上個循環內的值單次比較算法

f[i][v] = max {f[ i - 1 ][ v ], f[ i ][ v - vi ] + wi }優化

徹底揹包:max { f[ i-1 ][ v ], f[ i ][ v - c * vi ]+ c * wi } 時間 O(VN) 空間 O(V)spa

for(i=1; i<=n; i++)code

for(j=v[ i ]; j <= v; j++ )//順序保證同一個循環內的值相互比較blog

f[i][v] = max { f[ i-1 ][ v ], f[ i ][ v - c * vi ]+ c * wi }ip

多重揹包:max { f[ i-1 ][ v ], f[ i ][ v - ci * vi ]+ ci * wi | 0 <= ci * vi <= v}ci

時間 O(v*n*∑ci)it

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

for(k=1; k <= ci; k--)

for(j=v; j >= vi; j--)

f[v] = max( f[v], f[v - vi] + wi );

時間 O(v*n*∑log ci)

if ( ci * vi > v ) completePack( vi, wi );

else {

int i=1;

while( i<ci )

{

zeroOnePack( i * vi, i * wi );

ci - = i;

i+=i;

}zeroOnePack( ci * vi , ci * wi );

}



01揹包  hdu 2602描述:
現有 n 件物品,一個最大容量爲 w 的揹包。第 i 件物品重量爲 wi ,價值爲 vi 。
已知對於一件物品,你必須選擇取或不取,且每件物品只能被取一次(這就是「0/1」的含義)。
求放置哪幾件物品進揹包,使得揹包中物品價值最大(或是求最大價值是多少等衍生問題)。

狀態轉化方程
  f[i][V]= max {f[i-1][V-vi]+wi,f[i-1][V]}
優化算法 f[v]=max{f[V],f[V-vi]}

代碼以下:
// O1揹包。。 #include<iostream> using namespace std; #define MAX(a,b) ((a)>(b)?(a):(b)) struct node { int val,cap; }; node in [1000]; int re [1001]; int main() { int t,n,v,i,j,k; cin >> t; while(t--) { memset(re,0,sizeof(re)); cin >> n >> v; for (i=0; i<n; i++) cin >> in[i].val; for (i=0; i<n; i++) cin >> in[i].cap; for (i=0; i<n; i++) for (j=v ;j>=in[i].cap; j--) re[j]=MAX(re[j],re[j-in[i].cap]+in[i].val); //for(i=0; i<=v; i++)cout << re[i] <<" ";cout<< endl; cout << re[v] << endl; } return 0; }
徹底揹包 hdu 1114

#include<iostream>
#include<climits>
#define MIN(a,b) ((a)>(b)?(b):(a))
#include<cmath>
using namespace std;

int w[505],v[505],f[10000];
int main()
{
    int t,bw,fw,n,i,j,k,ii;
    cin >> t;
    while(t--)
    {
            int len;  
            cin >> bw >> fw >> n;
            len = fw-bw;
            for(i=1; i<=n; i++)
            cin >> w[i] >> v[i];
            for(i=0; i<=len; i++)
                     f[i]=0;//f[i]=1000000;
            //f[0]=0;
            for(i=1; i<=n; i++)
                     for(j=v[i];j<=len;j++)
                     //f[j]=MIN(f[j],f[j-v[i]]+w[i]);
                     //for(ii=1; ii<=len; ii++)cout << f[ii]<<" ";cout << endl;
                     
                     if(j==v[i] || f[j-v[i]]>0)
                     {
                                  if(f[j]==0)f[j]=f[j-v[i]]+w[i];
                                  else f[j]=MIN(f[j],f[j-v[i]]+w[i]);
                     }
                     else continue;
                      if(f[len]==0) //if(f[len]==1000000)
             cout << "This is impossible." << endl;
            else cout <<"The minimum amount of money in the piggy-bank is "<<f[len]<<"."<<endl; 
    }
    return 0;
}

  多重揹包  hdu2191

#include<iostream>
#define MAX(a,b) ((a)>(b)?(a):(b))
using namespace std;

int V[101];
void zeroOnePack(int n, int tp, int th)
{
     for(int i=n; i>=tp; i--)
     V[i]=MAX(V[i],V[i-tp]+th);
     }
void completePack(int n, int tp, int th)
{
     for(int i=tp; i<=n; i++)
     V[i]=MAX(V[i],V[i-tp]+th); 
}
void multiPack(int n, int tp, int th, int tc)
{
     
     if( tp*tc > n )
     completePack(n,tp,th);
     else 
     {
          int i=1;
          while(i<tc)
          {
                    zeroOnePack(n,tp*i,th*i);
                    tc-=i;
                    i+=i;            
          }zeroOnePack(n,tp*tc,th*tc); 
     }
}
int main()
{
    int p[101],h[101],c[101];
    int t,n,m;
    cin >> t;
    while(t--)
    {
              int i,j,k;
              cin >> n >> m;
              for (i=1; i<=m; i++)               
              cin >> p[i] >> h[i] >> c[i];
              for(i=0; i<=n; i++)V[i]=0; 
              for(i=1; i<=m; i++)
              multiPack(n,p[i],h[i],c[i]);
              //for(i=1; i<=n;i++)cout << V[i]<<" ";cout << endl;
              cout << V[n] << endl;
    }
    return 0;
}
相關文章
相關標籤/搜索