题目
有2n个棋子排成一行,开始为位置白子全部在左边,黑子全部在右边,如下图为n=5的情况:
移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如n=5时,成为:
任务:编程打印出移动过程。
输入输出格式
输入格式
一个整数n。
输出格式
若干行,表示初始状态和每次移动的状态,用o表示白子,*表示黑子,-表示空行。
输入输出样例
输入样例
7
输出样例
ooooooo*******--
oooooo--******o*
oooooo******--o*
ooooo--*****o*o*
ooooo*****--o*o*
oooo--****o*o*o*
oooo****--o*o*o*
ooo--***o*o*o*o*
ooo*o**--*o*o*o*
o--*o**oo*o*o*o*
o*o*o*--o*o*o*o*
--o*o*o*o*o*o*o*
解析
我们先分析一下样例
ooooooo*******--
oooooo--******o*
oooooo******--o*
ooooo--*****o*o*
ooooo*****--o*o*
oooo--****o*o*o*
oooo****--o*o*o*
ooo--***o*o*o*o*
ooo*o**--*o*o*o*
o--*o**oo*o*o*o*
o*o*o*--o*o*o*o*
--o*o*o*o*o*o*o*
每两行分一组的时候,可以很明显地看到规律.
- 中间的 "o*" 与 "--" 交换
- 最左边的 "**" 与 "--" 交换
然而后四行并没有什么规律,可以采用打表.
打表原理:
ooo*o**--* o*o*o*
o--*o**oo* o*o*o*
o*o*o*--o* o*o*o*
--o*o*o*o* o*o*o*
后6个字符为固定的"o*o*o*"
于是只要记录
ooo*o**--*,
o--*o**oo*,
o*o*o*--o*,
--o*o*o*o*
#include<iostream>
#include<algorithm>
using namespace std;
int n;
char ch[205];
void output(){//输出
for(int i=0;i<2*n+2;i++){
putchar(ch[i]);
}
putchar('\n');
}
void movechess(int start,int end){//移动棋子
swap(ch[start],ch[end]);
swap(ch[start+1],ch[end+1]);
output();
}
string out[4]={"ooo*o**--*","o--*o**oo*","o*o*o*--o*","--o*o*o*o*"};
int main(){
cin>>n;
//打印初始状态
for(int i=0;i<n;i++){
ch[i]='o';
}
for(int i=n;i<2*n;i++){
ch[i]='*';
}
ch[2*n]='-';
ch[2*n+1]='-';
output();
int len=n;
while(true){
movechess(len-1,2*len);//中间的"o*"与"--"交换
len--;
if(len==3){
break;
}//不符合上述规律直接打表输出
movechess(len,2*len);//最左边的"**"与"--"交换
}
string ss;
for(int i=0;i<n-4;i++){
ss+="o*";
}
for(int i=0;i<4;i++){
cout<<out[i]<<ss<<endl;
}
return 0;
}