首页 > 试题广场 >

【模板】01背包

[编程题]【模板】01背包
  • 热度指数:24534 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}你有一个背包,最大容量为 V。现有 n 件物品,第 i 件物品的体积为 v_i,价值为 w_i。研究人员提出以下两种装填方案:
{\hspace{20pt}}_\texttt{1.}\, 不要求装满背包,求能获得的最大总价值;
{\hspace{20pt}}_\texttt{2.}\, 要求最终恰好装满背包,求能获得的最大总价值。若不存在使背包恰好装满的装法,则答案记为 0

输入描述:
\hspace{15pt}第一行输入两个整数 nV\left(1\leqq n,V\leqq 10^3\right),分别表示物品数量与背包容量。 
\hspace{15pt}此后 n 行,第 i 行输入两个整数 v_i, w_i\left(1\leqq v_i,w_i\leqq 10^3\right),分别表示第 i 件物品的体积与价值。


输出描述:
\hspace{15pt}输出两行: 
{\hspace{20pt}}_\texttt{1.}\, 第一行输出方案 \texttt{1} 的答案;
{\hspace{20pt}}_\texttt{2.}\, 第二行输出方案 \texttt{2} 的答案(若无解输出 0)。
示例1

输入

3 5
2 10
4 5
1 4

输出

14
9

说明

\hspace{15pt}在该组样例中: 
\hspace{23pt}\bullet\, 选择第 1、第 3 件物品即可获得最大价值 10+4=14(未装满);
\hspace{23pt}\bullet\, 选择第 2、第 3 件物品可使背包体积 4+1=5 恰好装满且价值最大,为 5+4=9
示例2

输入

3 8
12 6
11 8
6 8

输出

8
0

说明

\hspace{15pt}装第三个物品时总价值最大但是不满,装满背包无解。

备注:
\hspace{15pt}要求 O(nV) 的时间复杂度,O(V) 空间复杂度。
#include <limits.h>
#include <stdio.h>
#include <string.h>
int max(int a, int b) {
    return (a > b ? a : b);
}
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    int v[n + 1], w[n + 1], dp[m + 1];
    v[0] = 0, w[0] = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &v[i], &w[i]);
    }
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= v[i]; j--) {
            dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
        }
    }
    printf("%d\n", dp[m]);
    for (int i = 1; i <= m; i++) {
        dp[i] = INT_MIN;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= v[i]; j--) {
            dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
        }
    }
    printf("%d",(dp[m]>0?dp[m]:0));
    
    return 0;
}

发表于 2024-12-01 10:35:13 回复(0)
用例输入n=420时运行超时,有大佬能请教一下嘛😵
#include <stdio.h>
void fun(int* rra,int* rrb,int idx,int n,int v,int* ans1,int* ans2,int max){
    if(v>=0){
        *ans1=max>*ans1?max:*ans1;//背包能装的最大价值
    }
    if(v==0){
        *ans2=max>*ans2?max:*ans2;//背包恰好装满时能装的最大价值
        return;
    }
    for(int k=idx;k<n;k++){
        if(v-rra[k]>=0){
            idx=k+1;
            fun(rra,rrb,idx,n,v-rra[k],ans1,ans2,max+rrb[k]);//
        }
    }
}
int main() {
    int a, b, n, v,temp=0,ans1=0,ans2=0;
    scanf("%d %d", &n, &v);
    int rra[n],rrb[n];  
    while (scanf("%d %d", &a, &b) != EOF) { // 注意 while 处理多个 case
        // 64 位输出请用 printf("%lld") to
        if(a<=v){
            rra[temp]=a;//rra存储物品所占体积
            rrb[temp]=b;//rrb存储物体价值
            temp++;
        }
        //printf("%d\n", a + b);
    }
    fun(rra,rrb,0,temp,v,&ans1,&ans2,0);
    printf("%d\n",ans1);//输出答案一
    printf("%d\n",ans2);//输出答案二
    return 0;
}
发表于 2023-02-07 12:25:55 回复(0)
#include "stdio.h"
#include "stdlib.h"
// 抄榜一大佬的
int max(int a,int b)
{
    return a>b?a:b;
}

int main()
{
  int n,V; // 输入n, V
  scanf("%d%d",&n,&V);

  // 价值和重量
  int *vi=(int*)malloc(sizeof(int)*n);
  int *wi=(int*)malloc(sizeof(int)*n);
    
   for(int i=0;i<n;i++)
   { 
       scanf("%d %d",&vi[i],&wi[i]);
   }
  // dp内存
  int *dp=(int*)malloc(sizeof(int)*(V+1));
  dp[0]=0 ; // 小细节,这里不设置为0. 无法计算出正确答案

  for(int i=1;i<V+1;i++)
      dp[i]=0x80000000; // -2147483648
    
  int max_dp=0; // 第一问答案
  int j;
// 从上往下,从右往左:因为物品都只能用一次
  for(int i=1;i<=n;i++)
  {
      for(j=V;j>=vi[i-1];j--)
      {
          dp[j]=max(dp[j-vi[i-1]]+wi[i-1],dp[j]);
          if(dp[j]>max_dp) // 第一问答案就是恰好在某个容量时,可以达到的最大价值。一直记录最大值,就可以得到
            max_dp=dp[j]; // 记录更新第一问答案
      }    
  }  
  printf("%d\n",max_dp);  
  max_dp=dp[V];
 free(dp);
  if(max_dp<0)
    printf("0");
  else
    printf("%d",max_dp);       
}

发表于 2022-08-09 10:44:34 回复(0)