码迷,mamicode.com
首页 > 其他好文 > 详细

1.2 中国象棋将帅问题进一步讨论与扩展:如何用1个变量实现N重循环?[chinese chess]

时间:2014-06-25 13:23:00      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:style   blog   code   http   ext   color   

【题目】

假设在中国象棋中只剩下将帅两个棋子,国人都知道基本规则:将帅不能出九宫格,只能上下左右移动,不能斜向移动,同时将帅不能照面。问在这样条件下,所有可能将帅位置。要求在代码中只能使用一个字节存储变量

【分析】

 3种方案:

1)位运算实现1个byte存入和读取2个变量。

2)使用位域把几个不同的对象用一个字节的二进制位域来表示。比如

 C++ Code 
1
2
3
4
5
 
struct
{
    
unsigned char a: 4;
    
unsigned char b: 4;
} i;

3)使用1个变量表达2重循环。后面将会重点讨论该方案。(思考:如何用1个变量实现N重循环?)

【位运算】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/24
*/

#include<stdio.h>
#define HALF_BITS_LENGTH 4
#define FULLMASK 255
#define LMASK (FULLMASK << HALF_BITS_LENGTH)
#define RMASK (FULLMASK >> HALF_BITS_LENGTH)
#define RSET(b,n) (b = (b & LMASK) | (n))
#define LSET(b,n) (b = ((b & RMASK) | ((n) << HALF_BITS_LENGTH)))
#define RGET(b) (b & RMASK)
#define LGET(b) ((b & LMASK)>>HALF_BITS_LENGTH)
#define GRIDW 3

void Solution1()
{
    
unsigned char b;
    
for(LSET(b, 1); LGET(b) <= GRIDW * GRIDW; LSET(b, (LGET(b) + 1)))
    {
        
for(RSET(b, 1); RGET(b) <= GRIDW * GRIDW; RSET(b, (RGET(b)) + 1))
        {
            
if(LGET(b) % GRIDW != RGET(b) % GRIDW)
            {
                printf(
"A=%d,B=%d\n", LGET(b), RGET(b));
            }
        }
    }
}

位域

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/24
*/

struct
{
    
unsigned char a: 4;
    
unsigned char b: 4;
} i;

void Solution2()
{
    
for (i.a = 1; i.a <= 9; i.a++)
        
for(i.b = 1; i.b <= 9; i.b++)
            
if (i.a % 3 != i.b % 3// column not equal
                printf("%d,%d\n", i.a, i.b);
}

【单个变量】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/24
*/

void Solution3()
{
    
unsigned char i = 81;
    
while(i--)
    {
        
// i = 9*a+b, a = i/9, b = i%9
        if (i / 9 % 3 == i % 9 % 3)
            
continue;
        printf(
"%d,%d\n", i / 9, i % 9);
    }
}

“将”和“帅”各在自己的3*3的格子间里面走动,我们共需要验证9*9=81种位置关系,这也是i=81的由来。此外我们要明白 i/9和i%9的含义。我们知道,整数i可以由部两分组成,即i=(i/9)*9+i%9 。我们注意到,在i从81到0变化的过程中,i%9的变化相当于内层循环,i/9的变化相对于外层循环。

【扩展】

如何用1个变量实现N重循环?

先看个简单例子,1个变量实现2重循环。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
/*
    version: 1.0
    author: hellogiser
    blog: http://www.cnblogs.com/hellogiser
    date: 2014/6/24
*/

void LoopWith2Variables()
{
    
unsigned char i, j;
    
for(i = 0; i < 5; i++)
        
for(j = 0; j < 4; j++)
            printf(
"%d,%d", i, j);
}

void LoopWith1Variable()
{
    
unsigned char val = 4 * 5;
    
while(val--)
    {
        printf(
"%d,%d", (val / 4) % 5, val % 4);
    }
}

【总结】

对于 a*b = i ,我们可以用如下公式展开:

loop1=i%b;

loop2=(i/b)%a

其中loop1是内层循环,loop2是外层循环。

由此可以得出N重时的公式,假设 an * a(n-1) * ....... * a3 * a2 * a1 = N

loop1=N%a1

loop2=(N/(a1))%a2

loop3=(N/(a1a2))%a3

.....

loopN=(N/(a1a2.....a(n-1)))%an

【参考】

http://blog.csdn.net/kabini/article/details/2256421

http://blog.csdn.net/silenceburn/article/details/6133222

http://blog.csdn.net/zhongkeli/article/details/8779168

http://www.cnblogs.com/python27/archive/2012/04/10/2441114.html

【本文链接】

http://www.cnblogs.com/hellogiser/p/chinese-chess.html

1.2 中国象棋将帅问题进一步讨论与扩展:如何用1个变量实现N重循环?[chinese chess],布布扣,bubuko.com

1.2 中国象棋将帅问题进一步讨论与扩展:如何用1个变量实现N重循环?[chinese chess]

标签:style   blog   code   http   ext   color   

原文地址:http://www.cnblogs.com/hellogiser/p/chinese-chess.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!