一个基本算法题暴露出来的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++) …   由左至右

posted on 2013-06-01 23:56  一颗麦粒  阅读(7298)  评论(0编辑  收藏  举报

导航