• 一个基本算法题暴露出来的C++基础不扎实


    好久没有写算法了,写算法都手生了,这可不利于找工作呀,打算坚持每周看一下算法方面的相关知识。今天是第一次,所以就入门一下吧,看了一下鸡兔同笼的问题。问题如下:

    问题描述

    一个笼子里面关了鸡和兔子(鸡有2 只脚,兔子有4 只脚,没有例外)。已经知道了笼

    子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物

    输入数据

    第1 行是测试数据的组数n,后面跟着n 行输入。每组测试数据占1 行,包括一个正整

    数a (a < 32768)。

    输出要求

    n 行,每行输出对应一个输入。输出是两个正整数,第一个是最少的动物数,第二个是

    最多的动物数,两个正整数用空格分开。如果没有满足要求的情况出现,则输出2 个0。

    输入样例

    2

    3

    20

    输出样例

    0 0

    5 10

    题很简单,所以很快就写出了代码,如下: 

    #include <iostream>
    
    int main(){
    	int cnt; 
    	std::cin>>cnt;
    	for(int i=0;i<cnt;++i){
    		int legCnt = 0;
    		std::cin>>legCnt;
    		if(legCnt & 0x1){
    			std::cout <<0 <<" "<<0<<std::endl;
    		}else{
    			int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;
    			int cntMax = legCnt>>1;
    			std::cout << cntMin<<" " << cntMax<<std::endl;
    		}
    	}
    }

     运行了一下,结果竟然有问题,输入20时,输出时0 10,第一个最小的动物数明显计算有误,然后仔细看了一下代码, 问题出在一下语句中: 

    int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;

    其实逻辑很简单,最小的动物数应该时除以4,如果还剩2条腿,则在加一。理论上是没有问题的,但是上面的语句就是输出有误。然后改动如下就可以了

    int cntMin= (legCnt>>2) + ((legCnt&0x2) ? 1 :0);

     可以看出是由于运算符号的优先级引起的问题,然后又温了一下书: 

    在C/C++中,上面语句中涉及的运算符有 >> , + , & 和 ? : 四个,这四个的优先级从高到低依次为:

    +,  >>, & , ? : 

    这样,int cntMin= legCnt>>2 + legCnt&0x2 ? 1 :0;就被编译成一下运算顺序

    int cntMin = ((legCnt>>(2+legCnt))&0x2)? 1 : 0;

    所以才会得出20个腿算出的 最小可能动物数是 0。

    其实问题很简单的, 但是反映出对于C++的运算优先顺序还是不够熟悉。以为自己做的不错,结果一个小问题,就能查出自己的基本功有问题呀。还是要多练习一下了。wiki中找到 C/C++的运算优先级列在如下:

    优先级运算符叙述示例重载性结合性
    1 :: 作用域解析(C++专有) Class::age = 2; 由左至右
    2 ++ 后缀递增 i++  
    -- 后缀递减 i--  
    {} 组合 {i++;a*=i;}  
    () 函数调用或变量初始化 c_tor(int x, int y) : _x(x), _y(y * 10) {}  
    [] 数组访问 array[4] = 2;  
    . 以对象方式访问成员 obj.age = 34;
    -> 以指针方式访问成员 ptr->age = 34;  
    dynamic_cast 运行时检查类型转换(C++专有) Y& y = dynamic_cast<Y&>(x);
    static_cast 未经检查的类型转换(C++专有) Y& y = static_cast<Y&>(x);
    reinterpret_cast 重定义类型转换(C++专有) int const* p = reinterpret_cast<int const*>(0x1234);
    const_cast 更改非常量属性(C++专有) int* q = const_cast<int*>(p);
    typeid 获取类型信息(C++专有) std::type_info const& t = typeid(x);
    3 ++ 前缀递增 ++i   由右至左
    -- 前缀递减 --i  
    + 一元正号 int i = +1;  
    - 一元负号 int i = -1;  
    !
    not
    逻辑非
    !的备用拼写
    if (!done) …  
    ~
    compl
    按位取反
    ~的备用拼写
    flag1 = ~flag2;  
    (type) 强制类型转换 int i = (int)floatNum;  
    * 取指针指向的值 int data = *intPtr;  
    & 取变量的地址 int *intPtr = &data;  
    sizeof 某某的大小 size_t s = sizeof(int);
    new 动态内存分配(C++专有) long* pVar = new long;  
    new[] 动态数组内存分配(C++专有) long* array = new long[20];  
    delete 动态内存释放(C++专有) delete pVar;  
    delete[] 动态数组内存释放(C++专有) delete [] array;  
    4 .* 成员对象选择(C++专有) obj.*var = 24; 由左至右
    ->* 成员指针选择(C++专有) ptr->*var = 24;  
    5 * 乘法 int i = 2 * 4;  
    / 除法 float f = 10.0 / 3.0;  
    % 模数(取余) int rem = 4 % 3;  
    6 + 加法 int i = 2 + 3;  
    - 减法 int i = 5 - 1;  
    7 << 比特左移 int flags = 33 << 1;  
    >> 比特右移 int flags = 33 >> 1;  
    8 < 小于关系 if (i < 42) …  
    <= 小于等于关系 if (i <= 42) ...  
    > 大于关系 if (i > 42) …  
    >= 大于等于关系 if (i >= 42) ...  
    9 ==
    eq
    等于关系
    ==的备用拼写
    if (i == 42) ...  
    !=
    not_eq
    不等于关系
    !=的备用拼写
    if (i != 42) …  
    10 &
    bitand
    比特 AND
    &的备用拼写
    flag1 = flag2 & 42;  
    11 ^
    xor
    比特 XOR(独占or)
    ^的备用拼写
    flag1 = flag2 ^ 42;  
    12 |
    bitor
    比特 OR(包含or)
    |的备用拼写
    flag1 = flag2 | 42;  
    13 &&
    and
    逻辑 AND
    &&的备用拼写
    if (conditionA && conditionB) …  
    14 ||
    or
    逻辑 OR
    ||的备用拼写
    if (conditionA || conditionB) ...  
    15 c?t:f 三元条件运算 int i = a > b ? a : b; 由右至左
    16 = 直接赋值 int a = b;  
    += 以和赋值 a += 3;  
    -= 以差赋值 b -= 4;  
    *= 以乘赋值 a *= 5;  
    /= 以除赋值 a /= 2;  
    %= 以取余数赋值 a %= 3;  
    <<= 以比特左移赋值 flags <<= 2;  
    >>= 以比特右移赋值 flags >>= 2;  
    &=
    and_eq
    以比特AND赋值
    &=的备用拼写
    flags &= new_flags;  
    ^=
    xor_eq
    以比特XOR赋值
    ^=的备用拼写
    flags ^= new_flags;  
    |=
    or_eq
    以比特OR赋值
    |=的备用拼写
    flags |= new_flags;  
    17 throw 抛出异常 throw EClass(“Message”);
    18 , 逗号运算符 for (i = 0, j = 0; i < 10; i++, j++) …   由左至右
  • 相关阅读:
    hdu 1151
    DAG的最小路径覆盖和二分图的最大匹配
    二部图 最小点覆盖集与最大匹配的关系
    sdut 2151
    sdut Emergency
    作业
    Node.prototype.contains
    微博登录
    markdown
    Object.observe
  • 原文地址:https://www.cnblogs.com/kwliu/p/3113380.html
Copyright © 2020-2023  润新知