【解题报告】01背包

这应该是最基础的背包问题了,但正因为他的基础,他的思想会被用在很多DP题中,所以这里有必要对他剖析一下。

我们应该掌握的方法有两种

1、二维数组。
2、滚动数组。

后面那个一看就要高级一些,但是确实对动归没有太大的帮助,所以大家一定要把第一种方法学好!第二种方法我不做解释,只会黏贴代码,大家认真脑补一下应该也是可以理解的。

题目链接:
01背包问题

二维数组法:

这里定义背包叫做f[i][j],i代表前i个物品的总重为j,f[i][j]一起表示前i个物品的总共价值,所以我们就可以很明显的写出动态转移方程式:

 if(w[i]<=v) f[i][v]=max(f[i-1][v],f[i-1][v-w[i]]+c[i]);
    else f[i][v]=f[i-1][v];//important

然后大家应该都懂了,至于有些人问为什么中间看着这么别扭不直接这样写:

if(w[i]<=v) f[i+1][v+w[i]]=max(f[i][v]+c[i],f[i+1][v+w[i]]);
······ 

这当然是有原因的,是因为害怕一直往后扔会出现重复的情况!!!

下面上代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
int m,n;
int w[35],c[35];
int f[35][205];
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&w[i],&c[i]);
    }
    for(int i=1;i<=n;++i)
    {
        for(int v=m;v>0;--v)
        {
            if(w[i]<=v) f[i][v]=max(f[i-1][v],f[i-1][v-w[i]]+c[i]);
            else f[i][v]=f[i-1][v];//important
        }
    }
    printf("%d",f[n][m]);
    return 0;
}

P.s:中间加important的地方一定不要漏写了!

滚动数组法:

直接贴代码,大家脑补吧!

#include<cstdio>
#include<cstring>
using namespace std;
int bag[305];
int m,n;
int main()
{
    scanf("%d%d",&m,&n);
    int a,b;
    int limit=0;
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&a,&b);
        for(int j=limit;j>=0;--j)
        {
            if(bag[j]!=0||(j==0))
            {
                if(bag[j+a]<bag[j]+b&&j+a<=m)
                {
                    bag[j+a]=bag[j]+b;
                }
                if(limit<j+a)
                limit=j+a;
            }
        }
    }
    int ans=-1;
    for(int i=0;i<=m;++i)
    {
        if(bag[i]>ans)
        ans=bag[i];
    }
    printf("%d",ans);
    return 0;
}

上面写假了!

/*
    Name: P1048 采药
    Copyright: njc
    Author: Mudrobot
    Date: 2018/10/19 10:56:23
    Description: Dynamic Programming
*/
#include<bits/stdc++.h>
#define gc() getchar()//caution!!!
#define N 1004
using namespace std;
/*inline char gc() {
  static char buf[1<<18],*fs,*ft;
  return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<18,stdin)),fs==ft)?EOF:*fs++;
}*/
template<class T>
inline void read(T &aa) {
  register int k=0,f=1;
  register char c=gc();
  for (;!isdigit(c);c=gc()) if(c=='-')f=-1;
  for (;isdigit(c);c=gc()) k=(k<<3)+(k<<1)+(c-'0');
  aa=k*f;
}
template<class T>
inline void out(T x){if(x>9)out(x/10);putchar(x%10+'0');}
int dp[N],w[N],val[N],n,t;
int main()
{
    //freopen(".in", "r", stdin);freopen(".out", "w", stdout);
    scanf("%d%d",&t,&n);
    for(int i=1;i<=n;++i) scanf("%d%d",&w[i],&val[i]);
    for(int i=1;i<=n;++i){
        for(int j=t;j>=0;--j){
            if(j>=w[i])dp[j]=max(dp[j],dp[j-w[i]]+val[i]);
        }
    }
    printf("%d",dp[t]);
    //fclose(stdin);fclose(stdout);
    return 0;
}
/*
70 3
71 100
69 1
1 2
*/

谢谢采纳!

原文链接: https://www.cnblogs.com/mudrobot/p/13330904.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    【解题报告】01背包

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/367819

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午6:00
下一篇 2023年3月2日 下午6:00

相关推荐