小明的背包(01背包)C语言简单易懂,配图及error汇总

题目描述

小明有一个容量为 V的背包。

这天他去商场购物,商场一共有 N 件物品,第 i 种物品的体积为w[i],价值为 v[i]

小明想知道在购买的物品总体积不超过 V 的情况下所能获得的最大价值为多少,请你帮他算算。

输入描述

输入第 1 行包含两个正整数 N,V,表示商场物品的数量和小明的背包容量。

第 2∼N+1 行包含 2 个正整数 w,v,表示物品的体积和价值。

1≤N≤10^3,1≤V≤10^3,1≤w[i]​,v[i]​≤10^3。

#include <stdio.h>
#include <stdlib.h>
int dp[1001][1001]={0};
void package (int n,int v,int *w,int *c){
  for(int i=1;i<n+1;i++){
    for(int j=1;j<v+1;j++){
      if(j>=w[i]&&dp[i-1][j-w[i]]+c[i]>dp[i-1][j])
        dp[i][j]=dp[i-1][j-w[i]]+c[i];
      else dp[i][j]=dp[i-1][j];
    }
  }
}
int main(int argc, char *argv[])
{
  int n,v;
  scanf("%d %d",&n,&v);
  int w[1000]={0};
  int c[1000]={0};
  for(int i=1;i<n+1;i++){
    scanf("%d",&w[i]);
    scanf("%d",&c[i]);
  }
  package(n,v,w,c);
  printf("%d",dp[n][v]);
  return 0;
}

易错点00:

         有人会问啦,“为什么dp数组初始化大小要设为1001那么多,题目要求N和V都是小于等于1000的啊?”

        这是因为啊,在这里遍历dp数组的时候,要将第一个状态从dp[1][1]开始存入,i和j的初始值都设为了 1 ,C语言数组长度为n,下标就是0—n-1,要想从下标1开始,那么你的数组定义长度就要比题目给的范围大1。这样才能保证不越界。

易错点01:

 

 在函数调用数组的位置,我就在第一次写这道题的时候就犯了错,所以把它写进易错点。

正确的在函数头调用数组及指针的格式是:类型+“空格”+“*”+数组名

而在主函数中调用函数的时候括号里面直接敲数组名就够了

 易错点02: 

这一步就是状态转移方程 用来比较选择放第i件 和 选择不放第i件那个价值更大,然后把值大的一个赋值给dp[i][j];要注意的就要提前判断一下 j 和w[i]的大小,因为如果没有比较的话,j-w[i]会出现负值,error:数组的下标越界;

 易错点03:

 在循环输入w[i],c[i]的代码当中的for循环使用上要注意,

总结了一下,这里的会出现以下错误情况

        一种错误:

 这样会出现报错越界情况,原因就在于数组就只能又数组长度n个位置可以填入,下标是0—n-1如果是for(i=1;i<=n;i++)到最后会出现i=n这一情况。

上面这是正确而且能通过题目的代码,可是仔细看一下,这个正确的代码和上面错误的代码就只有i的条件上不一样。一个是i<n+1,一个是i<=n;细想一下,这是一样的啊!!可就是i<=n会出现越界的情况,这。。我也不知道为什么,还请各位给我讲讲。

        另一种错误: 

这样的形式也是错的,虽然不会出现越界的报错,但是数组是从a[0]开始保存的,是不符合题意的

更改方法就是将a[i]变成a[i+1]。如图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值