信息学奥赛一本通(1327:【例7.6】黑白棋子的移动)

1327:【例7.6】黑白棋子的移动


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 5394     通过数: 2403

【题目描述】

有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*

【分析】

        我们先从 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 <stdio.h>
int n,st,sp;
char c[101];

void print()
{
	int i;
	printf("step%2d:",st);
	for(i=1;i<=2*n+2;i++)
		printf("%c",c[i]);
	printf("\n");
	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()
{
	scanf("%d",&n);
	init(n);
	mv(n);
	return 0;
}

http://ybt.ssoier.cn:8088/problem_show.php?pid=1327

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值