暑假集训.2(背包问题)

第一种,0-1背包

            0-1背包大多解决的的问题时,给你一个容量为V的背包,给你n个物品以及每个物品的价值和重量,每个物品中有一个。

让你在不超出背包容量的情况下尽可以装价值更大的东西。(刚开始可以用二维dp数组来写,也可以优化为以为数组节约空间)。

eg:
     5 10                              
     6 3 5 4 6        0  0  6  6  6  6  6  6  6  6  6
     2 2 6 5 4        0  0  6  6  9  9  9  9  9  9  9                             
                      0  0  6  6  6  6  6  6 11 11 14
                      0  0  6  6  9  9  9 10 11 13 14
                      0  0  6  6  9  9 12 12 15 15 15 

                      

二维dp解法:

#include <iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<deque>
#include<queue>
#include<vector>
#include<stack>
#include<ctime>
using namespace std;
#define eps 1e-10
#define INF 0x3f3f3f3f
typedef long long LL;
int main()
{
    LL dp[1000][1000],n,m,v[1000],c[1000];
    memset(dp,0,sizeof(0));
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>v[i];
    for(int i=1;i<=n;i++)
        cin>>c[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<c[i];j++)
            dp[i][j]=dp[i-1][j];
        for(int j=c[i];j<=m;j++)
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+v[i]);
    }
    for(int i=1;i<=n;i++)//输出背包大小不超过输入容量下的能装的最大价值
    {
        for(int j=0;j<=m;j++)
            cout<<dp[i][j]<<" ";
        cout<<endl;
    }
 
 
}

优化一维数组

#include <iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<deque>
#include<queue>
#include<vector>
#include<stack>
#include<ctime>
using namespace std;
#define eps 1e-10
#define INF 0x3f3f3f3f
typedef long long LL;
int main()
{
    LL dp[1000],n,m,v[1000],c[1000];
    memset(dp,0,sizeof(0));
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>v[i];
    for(int i=1;i<=n;i++)
        cin>>c[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=c[i];j--)
        dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
        for(int j=0;j<=m;j++)
            cout<<dp[j]<<" ";
        cout<<endl;
    }
 
 
}

第二种,完全背包:

           完全被包与0-1背包的区别就是完全背包里的物品数量是无限个,完全背包与0-1背包代码实现相差不大

dp数组正着更新是完全背包,倒着更新是0-1背包;

#include <iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<deque>
#include<queue>
#include<vector>
#include<stack>
#include<ctime>
using namespace std;
#define eps 1e-10
#define INF 0x3f3f3f3f
typedef long long LL;
int main()
{
    LL dp[1000],n,m,v[1000],c[1000];
    memset(dp,0,sizeof(0));
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>v[i];
    for(int i=1;i<=n;i++)
        cin>>c[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=c[i];j<=m;j--)
        dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
        for(int j=0;j<=m;j++)
            cout<<dp[j]<<" ";
        cout<<endl;
    }
 
 
}

第三种,多重背包:

          多重背包就是背包里物品数量不为一但是有限,相当于介于0-1背包与完全背包之间,一般解决多重背包问题把

0-1背包与完全背包结合起来使用,而且一般0-1背包可以用二进制压缩来优化,降低时间复杂度

#include <iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<deque>
#include<queue>
#include<vector>
#include<stack>
#include<ctime>
using namespace std;
#define eps 1e-10
#define INF 0x3f3f3f3f
typedef long long LL;
int v[1005];
int d[1005];
int dp[100005];
int n,m;
void zero(int v)
{
     for(int i=m;i>=v;i--)
        {
            dp[i]=max(dp[i],dp[i-v]+v);
 
        }
}
void complete(int v)
{
     for(int i=v;i<=m;i++)
        {
            dp[i]=max(dp[i],dp[i-v]+v);
 
        }
}
void f(int v,int d)
{
    if(v*d>=m)
        complete(v);//完全背包
    else
    {
        int k=1;
        while(k<=d)
        {
            zero(k*v);//0-1背包
            d-=k;
            k*=2;//二进制优化
        }
        zero(v*d);
    }
}
int main()
{
    while((cin>>n>>m)&&(n||m))
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++)
            dp[i]=-INF;
        for(int i=1;i<=n;i++)
            cin>>v[i];
        for(int i=1;i<=n;i++)
            cin>>d[i];
        for(int i=1;i<=n;i++)
            f(v[i],d[i]);
        int ans=0;
        for(int i=1;i<=m;i++)
            if(dp[i]>0)
                ans++;
            cout<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42728740/article/details/81135321