• 黑白棋子的移动(分治)


    黑白棋子的移动(chessman
    【问题描述】
        有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形:
        ○○○○○●●●●●
        移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如n=5时,成为:
         ○●○●○●○●○●
    任务:编程打印出移动过程。
    【输入样例】chessman.in
        7
    【输出样例】chessman.out
    step 0:ooooooo*******--
    step 1:oooooo--******o*
    step 2:oooooo******--o*
    step 3:ooooo--*****o*o*
    step 4:ooooo*****--o*o*
    step 5:oooo--****o*o*o*
    step 6:oooo****--o*o*o*
    step 7:ooo--***o*o*o*o*
    step 8:ooo*o**--*o*o*o*
    step 9:o--*o**oo*o*o*o*
    step10:o*o*o*--o*o*o*o*
    step11:--o*o*o*o*o*o*o*
     
    【算法分析】
     我们先从n=4开始试试看,初始时:
                 ○○○○●●●●
    第1步:○○○——●●●○●  {—表示空位}
    第2步:○○○●○●●——●
    第3步:○——●○●●○○●
    第4步:○●○●○●——○●
    第5步:——○●○●○●○●
          如果n=5呢?我们继续尝试,希望看出一些规律,初始时:
                 ○○○○○●●●●●
    第1步:○○○○——●●●●○●
    第2步:○○○○●●●●——○●
           这样,n=5的问题又分解成了n=4的情况,下面只要再做一下n=4的5个步骤就行了。同理,n=6的情况又可以分解成n=5的情况,……,所以,对于一个规模为n的问题,我们很容易地就把他分治成了规模为n-1的相同类型子问题。
     
    刚开始一点思路都没有觉得问题特别复杂,其实根据我做的这一丢丢题看来,步骤或者说是过程描述性强的题目,都有一定的规律,可用递归递推去做。
    这样的题一定有一定的规律,如当n=5时,再稍加变动就恢复n=4时的情况,这就是有规律可循了,问题就变得简单;再好比前面汉诺塔的题目,题目会仔细
    说明怎样去移动,那就有规律可循了,不多解释了,和这个题情况一样,又会恢复到n-1的状态;(快夸我!QWQ)
    初始化--输出--移动n个棋子(函数)--怎样移动(函数)--移动后输出(输出函数)
     
    【代码】
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 using namespace std;
     5 int n,nowp,num;
     6 char c[100];
     7 void init(int);//初始化 
     8 void move(int);//移动 
     9 void mov(int);//移动的方案 
    10 int print();//输出 
    11 int main()
    12 {
    13     scanf("%d",&n);
    14     init(n);//初始化 
    15     mov(n);//怎么移动 
    16     return 0;
    17 }
    18 int print()
    19 {
    20     cout<<"step "<<num<<":";
    21     for(int i=1;i<=2*n+2;i++)//输出 
    22     cout<<c[i];
    23     cout<<endl;
    24     num++;    
    25 }
    26 void init(int n)
    27 {
    28     nowp=n*2+1;//有‘-’的第一个位置,也就是可以将棋子移到这个位置 
    29     for(int i=1;i<=n;i++)c[i]='o';//初始化 
    30     for(int i=n+1;i<=2*n;i++)c[i]='*';
    31     c[n*2+1]='-';c[n*2+2]='-';
    32     print();
    33 }
    34 void mov(int n)//移动的方案 
    35 {
    36     if(n==4)//如果是4*2个棋子 
    37     {
    38         move(4);move(8);move(2);move(7);move(1);//先移动第四个位置和第五个位置,再移动第8,9... 
    39     }
    40     else
    41     {
    42         move(n);move(2*n-1);mov(n-1);//前两个语句完成后,剩下棋子排列相当于移动n-1个棋子的方案 
    43     }
    44 }
    45 void move(int n)
    46 {
    47     for(int i=0;i<=1;i++)
    48     {
    49         c[nowp+i]=c[n+i];//现在有空格的位置被移动来棋子代替 
    50         c[n+i]='-';//移动后的位置变为‘-’; 
    51     }
    52     nowp=n;//现在的位置要改变 **** 
    53     print();
    54 }
  • 相关阅读:
    8051单片机指令和寻址方式
    C/C++的关系
    go JSON 读写到文件
    Oracle 对未提交事务的查询
    win8 iis 安装
    Silverlight 项目 对话框
    VisualSVN错误 Cannot query proxy blanket解决办法
    silverlight浏览器自适应问题
    windows server2003 多用户登陆问题解决办法
    silverlight 缺少对象错误
  • 原文地址:https://www.cnblogs.com/zzyh/p/6623490.html
Copyright © 2020-2023  润新知