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

    方法二:

    View Code
    #include<stdio.h>  
    #define BYTE unsigned char
    int main(void)
    {
    BYTE i = 81;
    while(i--)
    {
    if((i / 9) % 3 == (i % 9) % 3)
    continue;
    printf("A = %d, B = %d\n", i /9 + 1, i%9 + 1);
    }
    return 0;
    }

    “将”和“帅”各在自己的3*3的格子间里面走动,我们共需要验证9*9=81种位置关系,这也是i=81的由来。此外我们要明白 i/9和i%9的含义。我们知道,整数i可以由部两分组成,即var=(var/9)*9+var%9 ,其中var<n。我们注意到,在i从81到0变化的过程中,var%9的变化相当于内层循环,var/9的变话相对于外层循环。这样,作者就巧妙地用一个变量i同时获得了两个变量的数值。

    可以把变量i想象成一个两位九进制的变量,而i在计算机中存储的值是i的十进制表示。则i/9的计算机处理结果,即结果直接去掉小数点后部分的结果即是此九进制数的第二位,而i%9即是此九进制数的个位。本程序用此九进制数的第二位保存A的位置,个位表示B的位置。最大值为88,即为十进制的80.程序从十进制的80,即九进制的88遍历到十进制的0,即九进制的0。将符合条件的位置全部输出。

    问题扩展:如何利用一个变量达到三重循环的效果。也就是说,如果给定下面的循环:

     int counter = 0;

     for( int i = 0; i < 5; i++ )  

    for( int j = 0; j < 4; j++ )   

    for( int k = 0; k < 3; k++ )   

    {    

    System.out.println("counter="+counter+"\t, i="+i+", j="+j+", k="+k);    

    counter++;    

    }  

    其结果如下:  

    counter=0 , i=0, j=0, k=0  

    counter=1 , i=0, j=0, k=1  

    counter=2 , i=0, j=0, k=2  

    counter=3 , i=0, j=1, k=0  

    counter=4 , i=0, j=1, k=1    

    ....中间略  

    counter=59  , i=4, j=3, k=2

     问题是

    (1)我们如何用一个打印出相同的结果?

    (2)如果是N重循环呢?   

    面对第一个问题,实际上就是对原始的中国象棋将帅问题进行了一个扩展,即在棋盘上添加一个“王”,其行走规则和将帅 一样。于是棋盘变成了三国争霸:-) ,将帅王可以走动的格子数分别为3、4、5,它们之间的互斥条件可以按需要设定。        

    这时,就需要只用一个变量遍历一个三重循环。直观的方法是像方法一那样把一个4字节的INT拆开来用。

    我这里只关注方法二。        

    只用一个变量解决扩展的中国象棋将帅问题,我们的代码应该是如下的样子:   

    int var = 3*4*5;   

    while( var-- )   

    {     

    if( /** 冲突条件 **/ )//发生冲突      

       continue;     

    else            

    printf(/** 打印可行的位置 **/);    }

    在冲突条件中,我们需要知道var取得某个特定的值(即第var+1次循环)的时候的i,j,k分别是多少(这样我们才能判定将帅位置是否冲突)     

    从上例的结果中我们可以看到,counter的值(即当前的循环次数)和三元组(i,j,k)是一一对应的,越是外层的循环变化越慢,他们满足什么关系呢?     

     k的取值最好确定,我们都知道是var%3。     

    在原始的将帅问题中我们知道,j的值应该是 var/3,但是由于j上面还有一层循环,就需要做些调整,变成var/3%4     

    最外层循环i的值则为(var/(3*4))%5.           即:

    k=var%3      //其下没有循环了             

     j=var/3   //其下有几个循环长度为3的循环            

     i=var/(3*4). //其下有几个循环长度为3*4的循环      

    于是4重循环的公式我们也可以轻松得出:  

    for( int i = 0; i < 5; i++ )     

      for( int j = 0; j < 4; j++ )       

         for( int k = 0; k < 3; k++ )         

           for( int p = 0; p < 3; p++ )       

     p=var%2 //其下没有循环了   

    k=var/2      //其下有几个循环长度为2的循环   

    j=var/(2*3)) //其下有几个循环长度为2*3的循环   

    i=var/(2*3*4)//其下有几个循环长度2*3*4的循环      

    下面就是一个变量实现三重循环

    int var = 2*3*4*5;

    while( var-- > 0)

    {  

    System.out.println("var="+var+" , i="+((var/(2*3*4))%5)+

                                  ", j ="+((var/(2*3))%4)+",  

                                   k="+((var/2)%3)+",                                                       

                                   p="+var%2);

    }

    结果是:   

    var=119 , i=4, j=3, k=2, p=1   

    var=118 , i=4, j=3, k=2, p=0   

    var=117 , i=4, j=3, k=1, p=1   

    ...中间略   

    var=5 , i=0, j=0, k=2, p=1   

    var=4 , i=0, j=0, k=2, p=0   

    var=3 , i=0, j=0, k=1, p=1   

    var=2 , i=0, j=0, k=1, p=0   

    var=1 , i=0, j=0, k=0, p=1   

    var=0 , i=0, j=0, k=0, p=0        

     N重循环原理也是一样,就不再赘述了。

    源文来自http://www.cnblogs.com/bvbook/archive/2008/07/24/1250507.html

  • 相关阅读:
    ImageView的属性android:scaleType
    Java容器类List、ArrayList、Vector及map、HashTable、HashMap分别的区别. (转)
    Pro Andorid3第一章:Android平台简介
    Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
    归纳法(induction)
    dual graph
    Project和编程过程
    维度
    dos
    关于glfrustum与hemicube的真实长度的关系
  • 原文地址:https://www.cnblogs.com/fly1988happy/p/2256461.html
Copyright © 2011-2022 走看看