标签:空位 样例 move 黑白 step 棋子 7.6 移动
1327:【例7.6】黑白棋子的移动
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 1475 通过数: 617
【题目描述】
有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时,总是将中间的一对两个不同的棋子移到最右边的空位,然后再把最左边的黑棋子移到中间,如此往复,直到剩下四对黑白棋没有移动。
不过我们发现,这4对棋子的移法是一成不变的,不受其他棋子影响。
因此,这个条件就可以作为递归边界,得出最后5步的走法。
看输出样例,可以得到剩下4步的普适移法,即:
- 先将第4、5个棋子移到右边空位。
- 将第8、9位置的棋子移到先前的空位。
- 将2、3位置的棋子移到先前的空位。
- 将7、8位置的棋子移到先前的空位。
- 将5、6位置的棋子移到之前的空位。
惊讶的发现,每次移动都是将某对棋子移到两个空位上,那么n>4时呢?
同样的,也是将中间的一对移到空位上,再将最右边的一对黑棋移到先前的空位上,如此往复。
恍然大悟。
算法分析:
本题的关键点就在于这个空位的问题,抓住了这个点,本题也就迎刃而解,因此我们需要设置一个代表空位起始位置的变量sp。
另一个要点,也是代码核心组成部分,就是移动棋子这一块了,通过上面的分析,我们得出普适的两步:
- 把中间位置的一对黑白棋移到最右边。
- 把最左边的一对黑棋移到中间的空位上。
这就是分治的思想,将这个问题分解成了一个个子问题,这些问题就是要进行上面两步求解。
得出核心代码块:
for(j=0;j<2;j++) { a[sp+j]=a[k+j-1]; a[k+j-1]='-'; } sp=k-1;
接着把前面提到的n=4时的情况写出:
if(n==4) { move(4);move(8);move(2);move(7);move(1); }
还有n>4的情况:
move(n);move(n*2-1);mv(n-1);
样例代码:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; char a[101]; int sp,step=0,n; void print()//输出 { printf("step%2d:",step); for(int i=0;i<2*n+2;i++) printf("%c",a[i]); printf("\n"); step++; } void move(int k)//分治:移动 { int j; for(j=0;j<2;j++) { a[sp+j]=a[k+j-1]; a[k+j-1]='-'; } sp=k-1; print(); } void mv(int n)//递归求解 { int i,k; if(n==4) { move(4);move(8);move(2);move(7);move(1); } else { move(n);move(n*2-1);mv(n-1); } } int main() { int i; scanf("%d",&n); for(i=0;i<n;i++) a[i]='o'; for(i=n;i<2*n;i++) a[i]='*'; a[2*n]='-';a[2*n+1]='-'; sp=2*n;//初始化 print(); mv(n); return 0; }
标签:空位,样例,move,黑白,step,棋子,7.6,移动 来源: https://www.cnblogs.com/DarkValkyrie/p/10387968.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。