NOIP 装箱问题

简介: NOIP 装箱问题

题目:[NOIP2001]装箱问题 ,哈哈,我们今天来看一道很古老的题嘛,这是选自NOIP上的一道题,好了,我们一起来看看题意吧:

考虑到直接复制题目,或者截屏的方式不是很方便阅读,我就把直接题目链接放下面!

题目传送门: [NOIP2001]装箱问题

思路:

写过01背包的老板看到这道题时,嘴角微微上扬,说,这还不简单,分分钟AC😎

但是,我这里用另一种动态规划的思路

先说说为什么要用动态规划吧:如果用暴力法的话(枚举每个物品装箱还是不装箱),时间复杂度会很高 O(2^n) 😗, 我们需要降低时间复杂度。

举个例子:背包容量 20, 5个物品,体积分别为,1,2,2,4,5 ,若我们枚举每个物品放不放的话,时间复杂度是 2^5 ,我们思考下,可以发现我们放两个体积为2的物品和放一个体积为4的物品,对结果是没有影响的。 我们算出这些物品可以放出的体积有: 1,2,3,4,5,6,7,8,9,10,11,12,13,14 这里一共14次(不排除算错的可能哈😂),而暴力法的话,有32种情况。

我们采用动态规划的思想呢,时间复杂度为:物品个数*背包体积

我们来看看成功AC的代码吧:

二维数组版

#include<bits/stdc++.h>
using namespace std;
int n,total;
int v[20010];
int f[35][20010];
int main(){
    f[0][0]=1;
    cin>>total>>n;
    for(int i=1;i<=n;i++) cin>>v[i];
    /**
     * f[i][j] 表示 0到i 的物品能否填满容量为 j 的背包
     */
     for(int i=1;i<=n;i++){
         for(int j=0;j<=total;j++){
             // f[i-1][j] 就表示前面 i-1 件物品能否填满容量为j的背包
             // f[i-1][j-v[i]] 表示前面 i-1 件物品能否填满容量为j-v[i]的背包
             if(j>=v[i]) f[i][j]=f[i-1][j]||f[i-1][j-v[i]];
             else f[i][j]=f[i-1][j];
         }
     }
     int ans=0;
     for(int i=total;i>=0;i--){
         if(f[n][i]==1){
             ans = i;break;
         }
     }
     cout<<total-ans;
    return 0;
}

我这里放一张雨巨的图,便于大家理解

我们可以看到每一行的结果实际上只与上一行有关,所以啊,我们可以压缩一下

压缩时有个坑:我们遍历体积的时候,需要从大到小去遍历,这样是为了防止让一个物品多次放入背包(这波操作真的很有意思😜)

下面我直接放代码

一维数组版

#include<bits/stdc++.h>
using namespace std;
int n,total;
int v[20010];
int f[20010];
int main(){
    f[0]=1;
    cin>>total>>n;
    for(int i=1;i<=n;i++) cin>>v[i];
    for(int i=1;i<=n;i++){
         for(int j=total;j>=v[i];j--){
             f[j]=f[j]||f[j-v[i]];
         }
     }
     int ans=0;
     for(int i=total;i>=0;i--){
         if(f[i]==1){
             ans = i;break;
         }
     }
     cout<<total-ans;
    return 0;
}


相关文章
|
机器学习/深度学习 人工智能 网络架构
P1563 [NOIP2016 提高组] 玩具谜题(找规律,心要细,数学思维)
P1563 [NOIP2016 提高组] 玩具谜题(找规律,心要细,数学思维)
72 0
|
5月前
【洛谷 P1002】[NOIP2002 普及组] 过河卒 题解(递归+记忆化搜索)
`NOIP2002`普及组的过河卒问题是一个棋盘路径计数挑战。卒从$(0,0)$出发到$(n,m)$,只能向下或向右移动,马在$(c1,c2)$固定,控制某些点。任务是计算不受马阻挡的路径数。输入是目标和马的位置,输出是路径总数。使用动态规划和记忆化搜索避免重复计算,样例输入$(6,6,3,3)$输出$6$。代码中定义了$f(x,y)$计算$(x,y)$处的路径数,利用边界条件和递推关系计算。
70 0
|
5月前
【洛谷 P1088】[NOIP2004 普及组] 火星人 题解(全排列+向量)
**火星人问题摘要:** NOIP2004普及组竞赛中的题目,涉及火星人用手指的排列表示数字。人类需计算火星人数字与给定数值之和的新排列。给定火星人手指数N(≤10000),加上的数M(≤100),以及初始排列,要求输出新排列。30%的数据中N≤15,60%的数据中N≤50。使用`next_permutation`函数找到第M个排列。样例:N=5, M=3, 初始排列1 2 3 4 5,输出1 2 4 5 3。
47 0
|
5月前
【洛谷 P1093】[NOIP2007 普及组] 奖学金 题解(结构体排序)
**NOIP2007普及组奖学金问题**:根据学生语文、数学、英语三科成绩计算总分并排序。若总分相同,按语文成绩高者优先,再相同则学号小者靠前。程序需输出前5名学生的学号和总分。输入包括学生人数`n`和每人的三科成绩,输出为5行结果。示例输入和输出已给出,代码通过定义结构体和自定义比较器实现排序。
40 0
|
5月前
|
C++
【洛谷 P1042】[NOIP2003 普及组] 乒乓球 题解(模拟+向量)
`NOIP2003`普及组编程题:乒乓球比赛模拟。给定一系列球赛记录(WL序列),程序需按11分和21分制分析比分。输入含多个字符串,含W(华华得分)、L(对手得分)和E(结束标记)。输出每局比分,分制间空行间隔。样例:`WWWWWW...` → `11:0\n11:0\n1:1`(11分制)和`21:0\n2:1`(21分制)。代码使用C++,逐字符读取,当分差≥2且得分≥x时输出比分。
50 0
[算法刷题题解笔记] 洛谷 P1011 [NOIP1998 提高组] 车站 [数学|斐波那契|推导]
[算法刷题题解笔记] 洛谷 P1011 [NOIP1998 提高组] 车站 [数学|斐波那契|推导]
【蓝桥杯基础题】2017年省赛—九宫幻方
【蓝桥杯基础题】2017年省赛—九宫幻方
【蓝桥杯基础题】2017年省赛—九宫幻方
|
Java C语言 C++
【蓝桥杯基础题】2020年省赛填空题—既约分数
【蓝桥杯基础题】2020年省赛填空题—既约分数
【蓝桥杯基础题】2020年省赛填空题—既约分数
|
算法
【递归与递推】洛谷[NOIP2002 普及组] 过河卒
前言 本题来自洛谷P1002. 题目链接:[NOIP2002 普及组] 过河卒 - 洛谷
225 0
(数论)蓝桥杯AcWing 1205. 买不到的数目
(数论)蓝桥杯AcWing 1205. 买不到的数目
47 0