巧用二进制编程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
巧用二进制数思想编程方法例谈
浙江慈溪实验中学张利波315300
二进制数在计算机中有着非常重要的意义,在信息学竞赛中,巧妙使用二进制数的特点,可能使程序思路更加简洁明了,解题也变得相当简单,下面列举几个程序来说明。
例1、如图所示为一个城市街道简图,小明从A点出发到达B点。如果在每一个路口只能向右或向上走,问小明可有多少条行走路线?并输出每条路线。
问题分析:该题一般的方法可以用深度优先遍历或广度优
编程呢?根据题意,可以通过以下几个方面进行分析:
①行走方向只有两种向右走或向上走,那么我们不妨
用0表示向上走,1表示向左走;②根据路径从A点到B
点,不论走哪条路径,走的步数总是固定的,如图中就是7步,因此,我们可以确定二进制数的位数是7位;③根据行走方向,用“1”表示向右走,据图向右走的步数为4,用二进制数表示又产生一个约束条件,7位二进制数中的“1”的个数为4,同理,“0”的个数为3。
根据以上分析,原题即转换成对7位二进制数的筛选,范围在(0001111)2——(1111000)2之间,且分离各位数字,相加为4,符合上述条件的,即为可以行走的一条路线,要统计所有可行走路线,只要对每个符合条件的线路数量累加即可。参考程序中避免了十进制数转换成二进制数的操作,采用穷举所有7位的二进制数并对此进行筛选完成。参考程序如下。
#include"stdafx.h"
#include
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
time_t begin,end;
begin=clock();
int x;
int total=0;
for(int i=0X0000000F;i<0X00000079;i++)
{
int x=i;
//求i的二进制码中有多少个
x= (x & 0X55555555) + ((x >> 1) & 0X55555555);
x= (x & 0X33333333) + ((x >> 2) & 0X33333333);
x= (x & 0X0F0F0F0F) + ((x >> 4) & 0X0F0F0F0F);
x= (x & 0X00FF00FF) + ((x >> 8) & 0X00FF00FF);
x= (x & 0X0000FFFF) + ((x >> 16) & 0X0000FFFF);
if (x==4)
{
for (int j=6;j>=0;--j)
{
if (((1< cout<<"1"; else cout<<"0"; } cout< total++; } } cout< end=clock(); cout< } 例2、如下图,有一个无穷大的栈S ,在栈的右边排列着1,2,3,4,5共五个车厢。其中每个车厢可以向左行走,也可以先 进栈S 让后面的车厢通过。现已知第一个到达出口的是3号车厢,请写出所有可能的到达出口的车厢排列总数,并输出每种排列。(源自第八届信息学初赛普及组问题求解) 问题分析:这是一例典型的栈应用题,主要考察栈“先进后出”特点,如果用常规办法,如递归,也可能造成遗漏,用非递归办法则更为复杂。根据题意,我们可以通过以下几个方面进行分析: ①栈的操作只有两类:进栈和出栈,那么就可以用二进制数0、1表示,用“1”表示进栈,“0”表示出栈;②每个车厢经过栈操作(进栈出栈),如果车厢直接向左行走,可以理解成进栈后马上出栈,这样就可以把5个车厢的操作化解成10个动作,用10个二进制位数来表示;③根据栈操作,出栈必在进栈之后,则对应二进制数“1”的个数必不小于“0”个数;④题意中要求第一个到达出口的是3号车厢,可以确定二进制数的高4位数字为“1110”,表示1,2,3车厢进栈后,首个出栈车厢为第3个车厢,这样数据范围由原来10位缩小至低6位;⑤此外由题意不难发现,该6位上的二进制数字,含“1”的个数为2个,因此可以进一步框定数据范围在(001010)2——(110000)2,⑥最后一次操作不可能是进栈操作,因此数据最低位不能为1,即只能为偶数。参考程序如下。 #include "stdafx.h" #include 出口← ← S ↓ #include using namespace std; int _tmain(int argc, _TCHAR* argv[]) { time_t begin,end; begin=clock(); int total=0,x; for(int i=0X0000000A;i<0X00000031;++i) { if((i&1)==0) { x=i; x= (x & 0X55555555) + ((x >> 1) & 0X55555555); x= (x & 0X33333333) + ((x >> 2) & 0X33333333); x= (x & 0X0F0F0F0F) + ((x >> 4) & 0X0F0F0F0F); x= (x & 0X00FF00FF) + ((x >> 8) & 0X00FF00FF); x= (x & 0X0000FFFF) + ((x >> 16) & 0X0000FFFF); if(x==2) { total++; cout<<"1110"; for(int j=5;j>=0;--j) { if(((1< cout<<"0"; else cout<<"1"; } cout< } } } end=clock(); cout< return 0; } 通过以上两个程序,我们大致了解用二进制数编程的方法,那么适用该方法时,程序描述有哪些明显特点呢?下面是笔者归纳的一些特点: