黑白棋子的移動(分治)


黑白棋子的移動( 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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM