动态规划-背包问题

01背包

题意

 算法思路

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1005;
int v[MAXN];    // 体积
int w[MAXN];    // 价值 
int f[MAXN][MAXN];  // f[i][j], j体积下前i个物品的最大价值 

int main() 
{
    int n, m;   
    cin >> n >> m;
    for(int i = 1; i <= n; i++) 
        cin >> v[i] >> w[i];

    for(int i = 1; i <= n; i++) 
        for(int j = 1; j <= m; j++)
        {
            //  当前背包容量装不进第i个物品,则价值等于前i-1个物品
            if(j < v[i]) 
                f[i][j] = f[i - 1][j];
            // 能装,需进行决策是否选择第i个物品
            else    
                f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
        }           

    cout << f[n][m] << endl;

    return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int N,V;
int v[maxn],w[maxn];
int dp[maxn];
int main()
{
    int i,j;
    cin>>N>>V;
    for(i=1;i<=N;i++)
        cin>>v[i]>>w[i];
    for(i=1;i<=N;i++)
    {
        for(j=V;j>=v[i];j--)
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
    }
    cout<<dp[V]<<endl;
    return 0;
}

完全背包

题意

算法思路

 

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int N,V;
int v[maxn],w[maxn];
int dp[maxn];

int main()
{
    int i,j;
    cin>>N>>V;
    for(i=0;i<N;i++)
        cin>>v[i]>>w[i];
    for(i=0;i<N;i++)
    {
        for(j=v[i];j<=V;j++)
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
    }
    cout<<dp[V];
    return 0;
}

多重背包

题意

 算法思路

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int N,V;
int w[maxn],v[maxn],s[maxn];
int dp[maxn][maxn];
int main()
{
    int i,j,k;
    cin>>N>>V;
    for(i=1;i<=N;i++)
        cin>>v[i]>>w[i]>>s[i];
    for(i=1;i<=N;i++)
    {
        for(j=0;j<=V;j++)
        {
            for(k=0;k<=s[i]&&k*v[i]<=j;k++)
                dp[i][j]=max(dp[i][j],dp[i-1][j-k*v[i]]+k*w[i]);
        }
    }
    cout<<dp[N][V]<<endl;
    return 0;
}

若是数据范围有所调整

则该方法不可使用,可使用01背包+二进制优化的方法

#include<bits/stdc++.h>
using namespace std;
const int n=12010,m=2010;
int N,V;
int v[n],w[n];
int f[m];

int main()
{
    int i,j;
    cin>>N>>V;
    int cnt=0;
    for(i=0;i<N;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;

        int k=1;
        while(k<=c)
        {
           cnt++;
           v[cnt]=a*k;
           w[cnt]=b*k;
           c-=k;
           k*=2;
        }
        if(c>0)
        {
            cnt++;
            v[cnt]=a*c;
            w[cnt]=b*c;
        }
    }
    N=cnt;
    for(i=1;i<=N;i++)
    {
        for(j=V;j>=v[i];j--)
            f[j]=max(f[j],f[j-v[i]]+w[i]);
    }
    cout<<f[V]<<endl;
    return 0;
}

分组背包

题意

算法思路

#include<bits/stdc++.h>
using namespace std;
int s[110];
int v[110][110],w[110][110];
int f[110];

int main()
{
    int i,j,k;
    int N,V;
    cin>>N>>V;
    for(i=0;i<N;i++)
    {
        cin>>s[i];
        for(j=0;j<s[i];j++)
            cin>>v[i][j]>>w[i][j];
    }
    for(i=0;i<N;i++)
    {
        for(j=V;j>=0;j--)
        {
            for(k=0;k<s[i];k++)
            {
                if(j>=v[i][k])
                    f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
            }
        }
    }
    cout<<f[V]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/xiaofengzai/p/14418651.html