• 2018第九届蓝桥杯C/C++ B国赛 —— 第三题:格雷码


    格雷码

    格雷码是以n位的二进制来表示数。
    与普通的二进制表示不同的是,它要求相邻两个数字只能有1个数位不同。
    首尾两个数字也要求只有1位之差。

    有很多算法来生成格雷码。以下是较常见的一种:
    从编码全0开始生成。
    当产生第奇数个数时,只把当前数字最末位改变(0变1,1变0)
    当产生第偶数个数时,先找到最右边的一个1,把它左边的数字改变。
    用这个规则产生的4位格雷码序列如下:
    0000
    0001
    0011
    0010
    0110
    0111
    0101
    0100
    1100
    1101
    1111
    1110
    1010
    1011
    1001
    1000

    以下是实现代码,仔细分析其中逻辑,并填写划线部分缺少的代码。

    #include <stdio.h>
    void show(int a,int n)
    {
    	int i;
    	int msk = 1;
    	for(i=0; i<n-1; i++) msk = msk << 1;
    	for(i=0; i<n; i++){
    		printf((a & msk)? "1" : "0");
    		msk = msk >> 1;
    	}
    	printf("\n");
    } 
    
    
    void f(int n)
    {
    	int i;
    	int num = 1;
    	for(i=0; i<n; i++) num = num<<1;
    	
    	int a = 0;
    	for(i=0; i<num; i++){
    		show(a,n);
    		
    		if(i%2==0){
    			a = a ^ 1;
    		}
    		else{
    			a = _________________________ ; //填空
    		}
    	}
    }
    
    
    int main()
    {
    	f(4);
    	return 0;
    }
    

    代码

    #include <stdio.h>
    void show(int a,int n)
    {
        int i;
        int msk = 1;
        for(i=0; i<n-1; i++) msk = msk << 1;
        for(i=0; i<n; i++){
            printf((a & msk)? "1" : "0");
            msk = msk >> 1;
        }
        printf("\n");
    }
    
    
    void f(int n)
    {
        int i;
        int num = 1;
        for(i=0; i<n; i++) num = num<<1;
    
        int a = 0;
        for(i=0; i<num; i++){
            show(a,n);
    
            if(i%2==0){//当产生第奇数个数时,先找到最右边的一个1,把它左边的数字改变。
                a = a ^ 1;      //1=0001
                /*
                 * 异或运算,不同则为1,相同则为0,
                 * 如果a的最后一位数是1,则变为0,
                 * 左边三位数如果是1,与0不同,还是1,如果是0,与0相同,还是0;
                 * 如果a的最后一位数是0,则变为1,
                 * 左边三位数如果是1,与0不同,还是1,如果是0,与0相同,还是0;
                 * 把一个数字与1异或将翻转数字的最后一位。
                 */
            }
            else{//由上可知,else处理的是偶数个数的情况,当产生第偶数个数时,先找到最右边的一个1,把它左边的数字改变;
                a=a^((a&(-a))<<1);
                /*
                 * 将a和-a相与,得到的结果是a的最右边的1加上末尾的0的数的大小,
                 * 再将结果左移一位就是要翻转的位,
                 * 最后与a异或一下就可翻转。
                 */
    //            a = _________________________ ; //填空
            }
        }
    }
    
    
    int main()
    {
        f(4);
        return 0;
    }
    
  • 相关阅读:
    SpringCloud使用注解+AOP+MQ来实现日志管理模块
    拦截器、过滤器、AOP的区别和联系
    Java对象为啥要实现Serializable接口?
    深入Quartz,优雅地管理你的定时任务
    Filter、FilterChain、FilterConfig 介绍
    过滤器 和 拦截器 的6个区别,别再傻傻分不清了
    SpringAOP + 注解实现日志管理
    Java序列化为什么必须实现 Serializable 接口???
    关于Java序列化的问题你真的会吗
    计算吻合率
  • 原文地址:https://www.cnblogs.com/AlexKing007/p/12338461.html
Copyright © 2020-2023  润新知