weinan030416

导航

01背包和完全背包

01背包

每种东西只能放一次

#include<iostream>
using namespace std;
#define maxn 1001
int dp[maxn];
int volumn[maxn],weight[maxn];

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>volumn[i]>>weight[i];
    }

    for(int i=1;i<=n;i++)//依次枚举每个物品
    {
        for(int j=m;j>=volumn[i];j--)
        {
            dp[j]=max(dp[j],dp[j-volumn[i]]+weight[i]);//判断放还是不放物品价值高
        }
    }
    // for(int i=0;i<maxn;i++)
    // cout<<dp[i]<<endl;//dp[i]表示背包容量为i时放东西的最大价值
    cout<<dp[m]<<endl;//输出背包容量为m时东西的最大价值
}

 

测试数据

4 100
100 100
50 60
50 60
30 100

结果

160

变式

 

Daruk的攻击力上限是W,他可以一次性粉碎重量之和不超过W的任意多个岩石。

假设有N个重量不同的岩石,其中第i个岩石的重量是G[i]。

请问,Daruk一次攻击最多能粉碎的最大重量的岩石是多少?

 

输入

 

第一行两个整数,分别代表W和N。

以后N行,每行一个正整数表示G[i]。

 

输出

 

一个整数,表示Daruk一次攻击能粉碎的最大岩石重量。

 攻击力上限为背包,岩石体积和价值相等

输入样例 1 

20 5
7
5
4
18
1

输出样例 1

19
#include<iostream>
using namespace std;
#define maxn 1001
int dp[maxn];
int volumn[maxn],weight[maxn];

int main()
{
    int n,m;
    cin>>m>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>volumn[i];
        weight[i]=volumn[i];
    }

    for(int i=1;i<=n;i++)//依次枚举每个物品
    {
        for(int j=m;j>=volumn[i];j--)
        {
            dp[j]=max(dp[j],dp[j-volumn[i]]+weight[i]);//判断放还是不放物品价值高
        }
    }
    // for(int i=0;i<maxn;i++)
    // cout<<dp[i]<<endl;//dp[i]表示背包容量为i时放东西的最大价值
    cout<<dp[m]<<endl;//输出背包容量为m时东西的最大价值
}

本题目数字超过

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> 
using namespace std;

int n,half,m,g[50];
unsigned int w,ans,a[(1<<24)+1];

void calc(unsigned int val)
{
    int rest=w-val;
    int l=1,r=m;
    while(l<r)
    {
        int mid=(l+r+1)/2;
        if(a[mid]<=rest)    l=mid;
        else    r=mid-1;
    }
    ans=max(ans,a[l]+val);
}

void dfs1(int i,unsigned int sum)
{
    if(i==half)
    {
        a[++m]=sum;
        return;
    }
    dfs1(i+1,sum);
    if(sum+g[i]<=w)    dfs1(i+1,sum+g[i]);
}

void dfs2(int i,unsigned int sum)
{
    if(i==n+1)
    {
        calc(sum);
        return;
    }
    dfs2(i+1,sum);
    if(sum+g[i]<=w)    dfs2(i+1,sum+g[i]);
}

int main()
{
    cin>>w>>n;
    for(int i=1;i<=n;i++)    cin>>g[i];
    sort(g+1,g+n+1);
    reverse(g+1,g+n+1);
    half=n/2+3;
    dfs1(1,0);
    sort(a+1,a+m+1);
    m=unique(a+1,a+m+1)-(a+1);
    dfs2(half,0);
    cout<<ans<<endl;
}

 

😵‍💫

完全背包

每种东西可以放无数次

#include<iostream>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];

int main()
{
    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++)//j<=m,设定每个物品最小空间1,即相同的物品最多放入m件 
        {
            f[i][j]=f[i-1][j];//加上已经放入的物品价值 
            if(j>=v[i]) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);//放入还是不放 
        }
        cout<<f[n][m]<<endl;
        //f[i][m]只考虑前i件物品 
        //f[n][j]背包最大容量j 
}

 

测试数据

4 100
100 100
50 60
50 60
30 100

结果

300

posted on 2023-01-07 21:25  楠030416  阅读(15)  评论(0编辑  收藏  举报