棋子换位
有n个棋子A,n个棋子B,在棋盘上排成一行。
它们中间隔着一个空位,用“.”表示,比如:
AAA.BBB
现在需要所有的A棋子和B棋子交换位置。
移动棋子的规则是:
1. A棋子只能往右边移动,B棋子只能往左边移动。
2. 每个棋子可以移动到相邻的空位。
3. 每个棋子可以跳过相异的一个棋子落入空位(A跳过B或者B跳过A)。
AAA.BBB 可以走法:
移动A ==> AA.ABBB
移动B ==> AAAB.BB
跳走的例子:
AA.ABBB ==> AABA.BB
以下的程序完成了AB换位的功能,请仔细阅读分析源码,填写划线部分缺失的内容。
#include <stdio.h>
#include <string.h>
1 void move(char* data, int from, int to)//移动一个棋子A或者B到空位上 2 { 3 data[to] = data[from]; 4 data[from] = '.'; 5 } 6 7 int valid(char* data, int k)//判断是否越界 8 { 9 if(k<0 || k>=strlen(data)) return 0; 10 return 1; 11 } 12 13 void f(char* data) 14 { 15 int i; 16 int tag; 17 int dd = 0; // 移动方向 18 19 while(1){ 20 tag = 0; 21 for(i=0; i<strlen(data); i++){ 22 if(data[i]=='.') continue; 23 if(data[i]=='A') dd = 1; 24 if(data[i]=='B') dd = -1; 25 26 if(valid(data, i+dd) && valid(data,i+dd+dd) 27 && data[i+dd]!=data[i] && data[i+dd+dd]=='.'){ 28 //如果能跳... 29 move(data, i, i+dd+dd); 30 printf("jump:%s ", data); 31 tag = 1; 32 break; 33 } 34 } 35 36 if(tag) continue; 37 38 for(i=0; i<strlen(data); i++){ 39 if(data[i]=='.') continue; 40 if(data[i]=='A') dd = 1;//向右 41 if(data[i]=='B') dd = -1;//向左 42 43 if(valid(data, i+dd) && data[i+dd]=='.'){ 44 // 如果能移动... 45 if(valid(data, i+dd+dd) && valid(data,i-dd)&&data[i+dd+dd]==data[i-dd] ) continue; //填空位置 46 move(data, i, i+dd); 47 printf("move:%s ", data); 48 tag = 1; 49 break; 50 } 51 } 52 53 if(tag==0) break; 54 } 55 } 56 57 int main() 58 { 59 char data[] = "AAA.BBB"; 60 printf("%s ",data); 61 f(data); 62 return 0; 63 }
思路:
以下为程序运行时的输出:
初始:AAA.BBB
move:AA.ABBB
jump:AABA.BB
move:AABAB.B
jump:AAB.BAB
jump:A.BABAB
move:.ABABAB
jump:BA.ABAB
jump:BABA.AB
jump:BABABA.
move:BABAB.A
jump:BAB.BAA
jump:B.BABAA
move:BB.ABAA
jump:BBBA.AA
move:BBB.AAA
仔细想想,还是有规律的;注意看上面的第二行和第三行,从第二行的状态出发,走一次‘B’之后达到了一个状态:空点两侧都是‘B’了,也就是说空地两侧是相同的字符!——这个时候就不能再把最后一个B再向左移动(move)了,不然就卡死了!
下面的几个画横线的都是这样!这种题目确实不好想,解题思路应该进行一些调整,自己按照规则尝试运行运行,在自己模拟的过程中逐步发现规律,毕竟去掉这一行以后经常进入死循环!