[题目解析]装箱问题

装箱问题 (pack)

时间限制: 1000 ms 空间限制: 262144 KB

题目描述

社会实践是小学教育的重要组成部分,也是素质教育的一个重要环节,老师经常带同学们到工厂车间去参观。一天,在班主任的带领下,小明和他的同学来到了一间生产箱子的工厂,在工厂的仓库里有许多箱子,这些箱子被排成单独的一行,每个箱子都有一个体积,箱子的体积不大于1000个单位体积,体积小的可以放到体积大的箱子里面。仓库的经理想把一些箱子放进另一些箱子里面,以便使得左端有更多连续的空余位置。

基于安全因素的考虑,一个箱子最多能够装下一个比它小的箱子,并且只能尝试将左端的前K个箱子装入与之相邻的K(即K+1~2*K之间)个箱子中。

你的任务是帮助经理计算一下,在满足安全因素的情况下,左端有多少个箱子可以装入与之相邻的箱子中。

输入

第一行为一个整数N,表示箱子的总个数。第二行是N个整数,表示这N个箱子的尺寸。

输出

一个整数,表示左边有多少个箱子可以装入与之相邻的箱子中,即题目中的最大的K值。

样例输入

10
2 2 1 4 3 2 5 4 2 3

样例输出

4

数据范围限制

60%的数据N<=300
100%的数据N<=3000

提示

前4个箱子可以放入5~8个箱子中。 其中一种放法为,第1箱子装入第5个箱子中,第2个箱子装入第8个箱子中,第3个箱子装入第6个箱子中,第4个箱子装入第7个箱子中,这样左边最多可以空出4个箱子位置,除此之外,没有其它方式能使左边空出更多的位置。


思路:

我们需要看懂这个题目,这个题目的意思就是让我们尽可能的腾出左边的空间(注意,是左边,不是右边也不是中间)。如果还是有点不明白题意,那么我们再结合提示分析样例。

相信大家看完提示就可以明白题目的意思了,毕竟提示已经写得很清楚了。

接下来简单的想一想题目的做法,我们需要先一组一组试,怎么试呢?这个问题我们先放在一边,待会再解决。

现在我们需要解决一个问题,我们一组一组指的是什么呢?怎么样一组一组的循环呢?这个问题很简单,我们需要分半,这可不是分半查找,而是比如说N=8,那我们先试试将前八个分半试试能不能全部装进去,然后再试试前六个分半,然后再试试前四个分半,再试试前两个分半,以此类推。

我们现在知道了怎么循环,那我们接下来需要解决的就是怎么试。

怎么试呢?我们需要先考虑个问题,相信大家第一个想法肯定都是双层循环吧,可是要考虑一下啊,虽是双层循环,但是别忘了我们外面还有一层循环啊,也就是说有三层循环,还是有可能会超时的。

所以我们只能考虑单层循环的方法了,我们想想啊,我们是不是可以先排序,然后再用两个变量一个循环。但这样对不对呢?很遗憾,不对,因为你如果排了序,那么就会改变原有的序列,也就是说,第一次试它的序列顺序是没问题的,再往后数列就不一样了,这样答案也就不一样了。

所以说我们不能修改原数列,必须给它找个“替身”,也就是说,我们需要复制一遍这个数列,然后再改变。

想到这里,想必大家都明白了怎么写了吧,接下来,话不多说,上超全注释代码↓

#include<bits/stdc++.h>
using namespace std;
int n,k[3001],k1[3001];//箱子数量、K数组、K数组的“替身” 
int main()
{
 cin>>n;
 for(int i=1;i<=n;i++){
  cin>>k[i];
 }
 if(n%2==1){//如果是单数,那后面的分半操作有可能出错,所以我们需要将它转化成为双数 
  n--;
 }
 for(int i=n/2;i>=1;i--){//这就是我们上面说的一组一组循环 
  memset(k1,0,sizeof(k1));//记住每次要把K数组的“替身”置零 
  for(int j=1;j<=i*2;j++){//把K数组的“替身”伪装成K数组(其实就是复制) 
   k1[j]=k[j];
  }
  sort(k1+1,k1+i+1);//排序 
  sort(k1+i+1,k1+i*2+1);//排序 
  int g=1,s=i*2;//g是两个变量中的一个,s是查看当前数列中的数字数量的 
  for(int j=i+1;j<=i*2;j++){//开始我们试的过程 
   if(k1[g]<k1[j]){//如果K1[j]能装下K1[g]的话,那我们就装它! 
    g++;//代表左边的箱子装进去了一个 
    s--;//代表左边的箱子数量减一 
   }
   s--;//代表右边的箱子数量减一 
  }
  if(s==0){//如果左边的箱子全部都装进右边的箱子了 
   cout<<i;//直接输出,因为当前答案就是最大的 
   return 0;//结束 
  }
 }
 cout<<0;//如果实在没有办法的话输出0 
}

看完了这篇文章,你是不是会做这道题了呢?文明做题,禁止抄袭!有什么问题可以在下方评论区留言,我空闲时间会全部回复哦!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值