01背包问题


方法一:记忆化搜索

#include<algorithm>
#include<iostream>
#include<cstring>
const int N=1000;
int n,V;
int v[N],w[N];
int mem[N][N];
int max(int a,int b)
{
    return a>b?a:b;
}
int dfs(int x,int spV){
if(mem[x][spV]) return mem[x][spV];
int sum=0;
    if(x>n) return 0;
    else{
        if(spV>=v[x])sum= max(dfs(x+1,spV-v[x])+w[x],dfs(x+1,spV) );
        else sum= dfs(x+1,spV);
    }
    mem[x][spV]=sum;
    return sum;
}

int main()
{
    scanf("%d %d",&n,&V);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&v[i],&w[i]);
    }
    int ans=dfs(1,V);
    printf("%d",ans);
    return 0;
}

方法二:递归(倒序)

#include<algorithm>
#include<iostream>
#include<cstring>
const int N=1000;
int n,V;
int f[N][N];
int v[N],w[N];
int max(int a,int b){
    return a>b?a:b;
}
int main()
{
    scanf("%d %d",&n,&V);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&v[i],&w[i]);
    }
    for(int i=n;i>=1;i--)
    {
        for(int j=0;j<=V;j++)
        if(j<v[i]) f[i][j]=f[i+1][j];
        else if(j>=v[i]) f[i][j]=max(f[i+1][j],f[i+1][j-v[i]]+w[i]);
    }
    printf("%d",f[1][V]);
    return 0;
}

方法三:递归(正序)

#include<algorithm>
#include<iostream>
#include<cstring>
const int N=1000;
int n,V;
int f[N][N];
int v[N],w[N];
int max(int a,int b){
    return a>b?a:b;
}
int main()
{
    scanf("%d %d",&n,&V);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&v[i],&w[i]);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=V;j++)
        if(j<v[i]) f[i][j]=f[i-1][j];
        else if(j>=v[i]) f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
    }
    printf("%d",f[n][V]);
    return 0;
}

方法四:一维(最优解法)

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1005;
int v[MAXN];    // 物品体积
int w[MAXN];    // 物品价值 
int f[MAXN];    // f[j]表示体积不超过j的情况下可以获得的最大价值

int main() 
{
    int n, m;   
    cin >> n >> m;  // n表示物品个数,m表示背包容量

    // 输入每个物品的体积和价值
    for(int i = 1; i <= n; i++) 
        cin >> v[i] >> w[i];

    // 01背包一维解法
    for(int i = 1; i <= n; i++) 
        for(int j = m; j >= v[i]; j--)
            f[j] = max(f[j], f[j - v[i]] + w[i]);

    cout << f[m] << endl;   // 输出最大价值

    return 0;
}
posted @   爱学习的小许?  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示