“二十一天好习惯”第一期-15

本文介绍了蓝桥杯算法训练中的一道题目,涉及机器人A和B按照特定规则搭塔。通过将A和B与二进制的0和1对应,利用位运算和递归思想,巧妙地计算出所有可能的搭塔组合。代码实现中包含nbit函数用于计算二进制中1的数量,以及check函数判断当前组合是否合法。最终通过枚举所有可能的底层排列并判断是否满足条件,得出所有合法塔的种类数。
摘要由CSDN通过智能技术生成

前言:

今天继续分享下蓝桥杯算法训练题,难度较之前的有所增加,需要用到一定的算法知识,闲话不多说,直接看题。

题目描述:

X 星球的机器人表演拉拉队有两种服装,A 和 B。

他们这次表演的是搭机器人塔。

类似:

       A

     B B

    A B A

   A A B B

  B B B A B

A B A B B A

队内的组塔规则是:

A 只能站在 AA 或 BB 的肩上。

B 只能站在 AB 或 BA 的肩上。

你的任务是帮助拉拉队计算一下,在给定 A 与 B 的人数时,可以组成多少种花样的塔。

输入描述

输入一行两个整数 M,NM,NM,N(0<M,N<5000<M,N<5000<M,N<500),分别表示 A、B 的人数,保证人数合理性。

输出描述

要求输出一个整数,表示可以产生的花样种数。

输入输出样例

示例

输入

1 2

输出

3

 代码实现:

#include<bits/stdc++.h>
using namespace std;
int m,n; 
int nbit(int num){//计算num的二进制里有多少的1,采用位运算 
    int ans = 0;
    while(num!=0){
        num = (num-1) & num;//不断地与自己的-1做位运算 
        ans++;
    }
    return ans;
} 
bool check(int now,int floor){//now的二进制就代表当前底层的排列顺序,floor代表最底层机器人的个数也是层数 
    int num_a=0,num_b=0;
    for(int i = floor;i >= 1;i--){
        int count1 = nbit(now);//计算now的二进制里含有多少个1,也就是这一层机器人B的个数
        num_b+=count1;
        num_a+=(i-count1);//第i层共有i个机器人,count1个是B,那么i-count1个就是A
        
        //计算上一层的排列情况 
        now = now ^ (now>>1);//now右移一位,就实现了错位,然后与now自身取异或,就得到了我们需要的相邻两位取异或 
        now &= (1<<(i-1))-1;//但是最高位那一个异或的结果是多余的,这一步是消掉最高位的数 
        
        if(num_a > m || num_b >n ) return false;//如果当前情况机器人A或者B数量大于它的最大值,那么一定不符合 
    }
    return num_a == m && num_b == n;//计算完后如果A,B机器人个数符合输入,返回true 
}
int main(){
    cin>>m>>n;
    int floor = sqrt((m+n)*2);//底层人数,也就是塔的层数
    int ans = 0;
    for(int i = 0;i < (1 << floor);i++){//从全0到全1的二进制 
        if(check(i,floor)) ans++;//对每一种情况进行检查 
    }
    cout<<ans<<endl;
    return 0;
}

 解析:

这题机器人共有A,B两种,A只能放在AA或BB上,B只能放在AB或BA上,巧方法:这里的A,B可以看成二进制里的0,1。0与0异或得0对应:A能放在AA或BB上,1与0异或得1对应:B能放在AB或BA上。根据每一层机器人数量关系可得,机器人总数=所有层数相加,每一层机器人数=对应层数。解题总体思路为:

枚举从最底层的情况,再按规律往上递归推导最后对机器人AB的个数进行合法判断

代码中的nbit函数,作用是确定每一层有多少个1,也就是B机器人的个数 check函数中now = now ^ (now>>1);功能为推算出上面一层机器人的分布情况。now &= (1<<(i-1))-1作用是通过将最高位化为0其他位不变再与之前的二进制数进行逻辑与运算从而消去最高位。floor = sqrt((m+n)*2),是由等差数列求和公式S=n*(n+1)/2,是利用double型转int型数据向下取整的方法推算出来的。然后再便利从0到2*i-1的二进制数,每一种情况对应一种二进制数,然后判断是否合法后输出即可。

小结:

该题难点在于把A,B两种机器人和组塔规则与二进制01和异或运算实质是等价的,从而大大优化了代码,即代码量,其中nbit函数求二进制中有多少个1也十分有用,这题考察到的算法思想十分巧妙,可作为经典例题,之后遇到了类似的只出现AB两种情况按照一定规则排布都可以套用之中思想。今天的分享就到这里,如有错误,尽情指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值