zoukankan      html  css  js  c++  java
  • 编程之美 ---> 1.2中国象棋将帅问题

    上图,将帅不能碰面,列出将帅不碰面的所有可能情况,要求:程序只能用一个只有8位的变量(#define这样的就不算了)

    为了更加符合程序员的口味,给将帅位置编号如下:

    0--1--2

    |    |   |

    3--4--5

    |    |   |

    6--7--8

    输出将帅所有可能情况,(0,1)等等

    --------------------------------------------------------------------------------------------------------------------------------------------------

    思路一:程序框架应该如下,关键是怎么样用一个变量表示将帅位置.

    遍历将位置

           遍历帅位置

                如果将帅位置不矛盾,输出

    只用8位的变量,要表示2个数,看来可以试试位操作每个表示位置的变量4个位,4位可以表示0-15,足以!

    方法一:

    位字段(为此还复习了位操作...http://www.cnblogs.com/jiayith/p/3500367.html)

    如下:

    #include <iostream>
    
    using namespace std;
    
    /*定义一个结构体,两个标签,各自4位,总共一个变量的话为8位*/
    struct myBits
    {
        unsigned char a:4;   //4位可以表示0-15的值了
        unsigned char b:4;
    };
    
    
    int main(void)
    {
        myBits my;
    
        for (my.a=0;my.a<=8;my.a++)
        {
            for (my.b=0;my.b<=8;my.b++)
            {
                if (my.a%3!=my.b%3)
                {
                    cout<<"("<<(int)my.a<<","<<(int)my.b<<")"<<endl;
                }
            }
        }
    
        cin.get();
        return 0;
    }

     方法二:

    既然都用了位字段,那位操作也应该没什么问题

    用一个char,我的机器八位,左4位表示将的位置,右位表示帅的位置,关键是怎么给一个8位的char的左右半边赋值再获得左右半边的值.位操作!

    #include <iostream>
    
    /*下面几个宏用于掩码,在获得左右半边的值时用*/
    #define  FULLMASK 255                   // 11111111
    #define  RMASK (FULLMASK>>4)   //00001111
    #define  LMASK (FULLMASK<<4)   //11110000
    
    /*下面是几个获得左右半边值的宏*/
    #define GETR(t) (t&RMASK)   //获得右半边4位的值,用掩码,掩盖住左半边的值,注意这个位操作不改变原有值
    #define GETL(t) ((t&LMASK)>>4)   //获得左半边4位的值,先掩盖右4位,再把值右移4位,注意这里要价格括号...我猜临时值放在某寄存器里 
    
    /*下面是设置左右半边值的宏*/
    #define SETR(t,val) (t=(t&LMASK)|val)//((t=t&LMASK),(t=t|val))   //用十进制val设置右4位,但要保证val可以用4位表示,即val表示值的位在低4位.(这里先清空右四位,再与左4位全是0而右4位是值的val或)
    #define SETL(t,val) (t=((t&RMASK)|(val<<4)))//((t=t&RMASK),(t=t|(val<<4)))   //用十进制val设置左4位 (先清空左4位,再把val右边4位的值移动到左边,再与)
    
    int main(void)
    {
        using namespace std;
    
       unsigned char my;   //注意这里一定要用无符号的,要不放最高位为1就麻烦了.... 
    
        
        for (SETL(my,0);(int)GETL(my)<=8;SETL(my,(int)GETL(my)+1))
        {
            for (SETR(my,0);(int)GETR(my)<=8;SETR(my,(int)GETR(my)+1))
            {
                if (((int)GETL(my)%3)!=((int)GETR(my)%3))
                {
                    cout<<"("<<(int)GETL(my)<<","<<(int)GETR(my)<<")
    ";
                }
            }
        }
    
        cin.get();
        return 0;
    }

    --------------------------------------------------------------------------------------------------------------------------------------------------

     思路二:不用上面的程序模式了,换个思路.

    将有9种情况,帅也有9种情况,组合起来共81种情况.

    能不能用一个变量表示这81种情况,对于每个情况的值,获得将和帅的值???

    可以!

    将=0,帅=(0,1,2,3,4,5,6,7,8) 值可以从0到8

    将=1,帅=(0,1,2,3,4,5,6,7,8) 值可以从9到17

    将=2,帅=(0,1,2,3,4,5,6,7,8)  ..

    将=3,帅=(0,1,2,3,4,5,6,7,8) ..

    将=4,帅=(0,1,2,3,4,5,6,7,8)

    将=5,帅=(0,1,2,3,4,5,6,7,8)

    将=6,帅=(0,1,2,3,4,5,6,7,8)

    将=7,帅=(0,1,2,3,4,5,6,7,8)

    将=8,帅=(0,1,2,3,4,5,6,7,8) 值从72到80

    即用一个八位的值val表示所以上述从0到80的81种情况,

    val/9即将的值,val%9即帅的值,搞定!

    #include <iostream>
    
    
    int main(void)
    {
        using namespace std;
    
       char val=0;
       while (val<=80)
       {
           if ((val/9%3)!=(val%9%3))
           {
               cout<<"("<<val/9<<","<<val%9<<")"<<endl;
           }
           val++;
       }
    
        cin.get();
        return 0;
    }

    --------------------------------------------------------------------------------------------------------------------------------------------------

    总结:

    1.多角度看问题

    2.C/C++位操作的强大,及几种位操作运算符的使用

  • 相关阅读:
    HDU 1076 An Easy Task
    299 Train Swapping
    HDU 1092 A+B for InputOutput Practice (IV)
    HDU 1093 A+B for InputOutput Practice (V)
    HDU 1049 Climbing Worm
    HDU 1032 The 3n + 1 problem
    HDU 1089 A+B for InputOutput Practice (I)
    HDU 1091 A+B for InputOutput Practice (III)
    Vimperator
    成为高效程序员的搜索技巧[转自月光博客]
  • 原文地址:https://www.cnblogs.com/jiayith/p/3500497.html
Copyright © 2011-2022 走看看