黑白棋子的移动

题目描述

 

2n 个棋子(n≥4)排成一行,开始为位置白子全部在左边,黑子全部在右边,如下图为 n=5 的情况:

○○○○○●●●●●

移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如 n=5 时,成为:

○●○●○●○●○●

 

任务:编程打印出移动过程。

 

输入

一个整数

输出

移动过程

样例输入

7

样例输出

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* 

step 10:o*o*o*--o*o*o*o*

step 11:--o*o*o*o*o*o*o*

 

分析

这道题看似不怎么好做,但只要细心一点观察样例,就会发现这题是一道极水的题:每经过两步,'o' 和 '*' 的排列方式就和原来一样了,只不过数目上各减少了一个,还有不同的是后面又多了一个 'o*'。

但是样例中到了step 7(n == 4)的时候就没有规律了,因此后面的完全可以固输,在补全 'o*'。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring> 
 6 using namespace std;
 7 const int maxn = 1e5 + 5;
 8 int n;
 9 char a[maxn];
10 void final(int step)        //固输 
11 {
12     printf("step %d:%s%s\n", step, "ooo*o**--", a + 10);
13     printf("step %d:%s%s\n", ++step, "o--*o**oo", a + 10);
14     printf("step %d:%s%s\n", ++step, "o*o*o*--o", a + 10);
15     printf("step %d:%s%s\n", ++step, "--o*o*o*o", a + 10);
16     return;
17 }
18 void move(int n)
19 {
20     int step = 0; 
21     for(int i = n; i >= 4; --i)        //当 n >= 4 时循环模拟 
22     {
23         a[i + 1] = a[i + 2] = '*'; 
24         a[2 * i + 1] = a[2 * i + 2] = '-';
25         printf("step %d:%s\n", step, a + 1); step++;
26         a[2 * i + 1] = 'o'; a[2 * i + 2] = '*';
27         a[i] = a[i + 1] = '-';
28         printf("step %d:%s\n", step, a + 1); step++;    
29     }
30     final(step);
31 }
32 
33 int main()
34 {
35     freopen("chessman.in", "r", stdin);
36     freopen("chessman.out", "w", stdout);
37     scanf("%d", &n);
38     for(int i = 1; i <= n; ++i) a[i] = 'o';
39     for(int i = n + 1; i <= 2 * n; ++i) a[i] = '*';
40     a[2 * n + 1] = a[2 * n + 2] = '-'; 
41     move(n);
42     return 0;
43 }

 

posted @ 2018-03-03 21:28  mrclr  阅读(383)  评论(0编辑  收藏  举报