动态规划--背包问题(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;
}