士兵队列训练问题

2 篇文章 0 订阅

题意 hdoj1276 典型的队列问题,入门水题
题解:(第一次做普通队列,引用了别人的算法,优化了一下,题解记录学到的一点东西)
队列和数组之类的东西完全不同,和栈一样,被固定的顺序和进出卡的很死,所以在做队列的题目时,不能像数组一样思维
因为是3个人,所以首先按队列的大小来卡人数,初始化的时候,从1开始进入队列,然后因为是2,3删除交替出现,所以很容易想到用奇偶性来判断是删除2还是3,之后用循坏实现,在循坏的过程中,要先保证循坏的完整性,

int x=q.size();
                if(k%2==1){
                    for(i=0;i<x/2;i++){
                      m=q.front();//队列不能像数组一样任意位置删除,只能删除队列顶的,所以要对这个队列之前的元素重新排,就是把2之前的1,3之前的1和2重新挪到后面,保持相对位置的不变是核心思想
                      q.push(m);
                      q.pop();
                      q.pop();}
                    if(x%2==1){
                        m=q.front();
                        q.push(m);
                        q.pop();//因为循坏的次数少了一次,所以最后剩下的那个一定是奇数,所以一定不用删去,所以就放到队列末尾
                    }
                }

这个处理感觉很复杂,但确实很巧妙,将不符合的直接pop掉,但对于符合的也要先pop,不然没办法删除后面的,所以就把符合的挪的队列的后面(后进队列的自动排到后面了),然后直接删除就可以了,这里要注意,删除要进行两次,因为要先删除1位置,才能删除2位置,而循环进行了x/2次,这就意味着,如果有奇数,是删除不了的,所以要对最后那个奇数进行额外的处理,因为是奇数,所以肯定是不用删除的,所以就放到最后就可以了(实际上还是相当于重新赋值后删除)
然后对于3位置的进行删除

else{
                    for(i=0;i<x/3;i++){
                      m=q.front();
                      q.push(m);
                      q.pop();
                      m=q.front();
                      q.push(m);
                      q.pop();
                      q.pop();}//这个要进行两次的删除,因为要删除三个里面的前两个
                      while(x%3!=0){
                        --x;
                        m=q.front();
                        q.push(m);
                        q.pop();
                      }
                }

3位置的删除比较麻烦,因为要对前面两个进行操作,这时候就可以发现删除2和3的共同点了,都是把前面的值放到后面去,都要利用pop和front来实现,切记:队列的位置的是固定的,而且要从顶端开始操作!!!
之后,如果不整除3,同理,说明有剩余,这时候根据循环,把剩下的一个或者两个都放到后面就可以了,要充分利用size取大小
最后对于k的值进行自增就可以了,可以保证2和3的删除交替出现,然后从队列顶端输出,输出一次pop掉一个,保证可以继续输出下一个
注意:要把队列定义在大循环里,这样可以保证队列的初始化,队列不能用clear操作,很烦
第一个队列,谨记。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值