首页 > 试题广场 >

【模板】01背包

[编程题]【模板】01背包
  • 热度指数:20745 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
你有一个背包,最多能容纳的体积是V。

现在有n个物品,第i个物品的体积为v_i ,价值为w_i

(1)求这个背包至多能装多大价值的物品?
(2)若背包恰好装满,求至多能装多大价值的物品?

输入描述:
第一行两个整数n和V,表示物品个数和背包体积。
接下来n行,每行两个数v_iw_i,表示第i个物品的体积和价值。




输出描述:
输出有两行,第一行输出第一问的答案,第二行输出第二问的答案,如果无解请输出0。

示例1

输入

3 5
2 10
4 5
1 4

输出

14
9

说明

装第一个和第三个物品时总价值最大,但是装第二个和第三个物品可以使得背包恰好装满且总价值最大。 
示例2

输入

3 8
12 6
11 8
6 8

输出

8
0

说明

装第三个物品时总价值最大但是不满,装满背包无解。 

备注:
要求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)