一个基本算法题暴露出来的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) ... 
15c?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; 
17throw抛出异常throw EClass(“Message”);
18,逗号运算符for (i = 0, j = 0; i < 10; i++, j++) … 由左至右

转载于:https://www.cnblogs.com/kwliu/archive/2013/06/01/3113380.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值