题目描述
有2n个棋子(n≥4)排成一行,开始为位置白子全部在左边,黑子全部在右边,如下图为n=5的情况:
○○○○○●●●●●
移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如n=5时,成为:
○●○●○●○●○●
任务:编程打印出移动过程。
输入输出格式
输入格式:
一个整数n(n<=100)
输出格式:
若干行,表示初始状态和每次移动的状态,用"o"表示白子,"*"表示黑子,"-"表示空行。
输入输出样例
输入样例#1:
7
输出样例#1:
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*
稍微给新人普及一下分治思想: 所谓分治,从字面上来看,就是 分而治之。
通过这个思想我们可以把一个大的问题逐渐推成一个轻而易举能解决的问题,然后再对小问题进行简单的解决。这个分而治之的过程思想久称之为 分治 ;
然后我们来具体看题目. 【算法分析】 我们先从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的相同类型子问题。
数据结构如下:数组c[1…max]用来作为棋子移动的场所
,初始时,c[1]~c[n]存放白子(用字符o表示),
c[n+1]~c[2n]存放黑子(用字符*表示),c[2n+1]c[2n+2]
为空位置(用字符—表示)。最后结果在c[3]~c[2n+2]中。
接下来上程序,注解不是很详细,还请见谅啦.
#include<bits/stdc++.h>//万能头,推荐哦
using namespace std;
int n,st,sp;
char c[101];
void print() //打印
{
int i;
/*cout<<"step "<<st<<':';*/ //因为原题是需要输出step
//st的,这里没有删除,有兴趣的可以去试试.
for (i=1;i<=2*n+2;i++) cout<<c[i];//进行输出
cout<<endl;
st++;
}
void init(int n)//初始化
{
int i;
st=0;
sp=2*n+1;
for (i=1;i<=n;i++) c[i]='o';
for (i=n+1;i<=2*n;i++) c[i]='*';
c[2*n+1]='-';c[2*n+2]='-';
print();
}
void move(int k)//移动一步
{
int j;
for (j=0;j<=1;j++)
{
c[sp+j]=c[k+j];
c[k+j]='-';
}
sp=k;
print();
}
void mv(int n)//主要过程
{
int i,k;
if (n==4)//n等于4的情况要特殊处理
{
move(4); move(8); move(2); move(7); move(1);
}
else
{
move(n); move(2*n-1); mv(n-1);
}
}
int main()
{
cin>>n;
init(n);//init函数调用
mv(n);//mv函数调用,包含输出
}
ov.