【8月刷题打卡】装箱问题(背包问题)

115 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

[NOIP2001 普及组] 装箱问题

题目描述

有一个箱子容量为 VV,同时有 nn 个物品,每个物品有一个体积。

现在从 nn 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小。输出这个最小值。

输入格式

第一行共一个整数 VV,表示箱子容量。

第二行共一个整数 nn,表示物品总数。

接下来 nn 行,每行有一个正整数,表示第 ii 个物品的体积。

输出格式

  • 共一行一个整数,表示箱子最小剩余空间。

样例 #1

样例输入 #1

24
6
8
3
12
7
9
7

样例输出 #1

0

提示

对于 100%100\% 数据,满足 0<n300<n \le 301V200001 \le V \le 20000

【题目来源】

NOIP 2001 普及组第四题

解题思路

01背包简介

题意概要:

有 个物品和一个容量为 的背包,每个物品有重量 和价值 两种属性,要求选若干物品放入背包使背包中物品的总价值最大且背包中物品的总重量不超过背包的容量。 例题中已知条件有第 i 个物品的重量w[i],价值v[i],以及背包的总容量W。

核心代码:

for (int i = 1; i <= W; i++)
  for (int l = W - i; l >= 0; l--) 
    f[l + i] = max(f[l] + w[i], f[l + i]);
#include<iostream>
#include<cstdio>
using namespace std;
int V,n,w,dp[200005];//dp数组尽量开大点,一般6位数就行
int main()
{
   scanf("%d%d",&V,&n);//输入
   for(int i=1;i<=n;i++)
   {
     scanf("%d",&w);//可以不用数组存,每次循环计算也可以
     for(int j=V;j>=w;j--)
       if(dp[j]<dp[j-w]+w)
	 dp[j]=dp[j-w]+w;//把能装的最大值给解出
   }
   printf("%d",V-dp[V]);//V-最大值的结果便是能装的最小空间
   return 0;//好习惯!
}