【输入】
有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形:
○○○○○●●●●●
移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如n=5时,成为:
○●○●○●○●○●
任务:编程打印出移动过程。
【输入】
输入n。
【输出】
移动过程。
【输入样例】
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*
step10:o*o*o*--o*o*o*o*
step11:--o*o*o*o*o*o*o*
题解:
这题看似毫无头绪,然而徒有其表(虽然代码有点多),只需稍加探索就能找到其中的奥秘
( ̄y▽, ̄)╭
first:
我们得知道它输出有多少行,非常好找,是2n-3+1(别问我为什么)
我们有发现除了从倒数第一行到倒数第4行,都是从第一个白与黑相交的两个棋子移到空地上,然后把空地与倒数2*(i-1)+1个棋与倒数2*(i-1)+2个棋调换(很简单对吧!)
then:
直到倒数第四个,把第一个形成“*o”的两个移到空位上,之后把刚刚移的两个棋中的‘*’前一个与前两个的‘o’放到空位上(把图画出来就能推了)
last:
把第一个与第二个棋放到空地上
OK:
上代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,x=0,as=0;
cin>>n;
as=n*2-3+1;//求行数
char a[10001]={0};
int p=0,f=2,k=2*n+1;
for(int i=1;i<=n;i++)
{
a[i]='o';
a[i+n]='*';//初始化
}
a[2*n+1]='-';
a[2*n+2]='-';
n*=2;
n+=2;
for(int j=1;j<=as;j++)
{
printf("step%2d:",x);//格式
if(j==as)
{
swap(a[1],a[k-1]);
swap(a[2],a[k]);
for(int i=1;i<=n;i++)
{
cout<<a[i];
}
//最后处理
return 0;
}else if(x==0)
{
//输出初始状态
for(int i=1;i<=n;i++)
{
cout<<a[i];
}
x++;
cout<<endl;
continue;
}else if(as-1-x<=3)//最后4步
{
if(x%2==0)
{
swap(a[k],a[p+1]);
swap(a[k-1],a[p]);
}else
{
swap(a[p-1],a[k]);
swap(a[p-2],a[k-1]);
p-=2;
k-=1;
}
}else//常见情况
{
if(x%2!=0)
{
p=(n-f)/2;
swap(a[p],a[k]);
swap(a[p+1],a[k+1]);
}else
{
swap(a[p],a[k-1]);
swap(a[p+1],a[k-2]);
k-=2;
f+=2;
}
}
for(int i=1;i<=n;i++)
{
cout<<a[i];
}
cout<<endl;
x++;
}
return 0;
}