第七届蓝桥杯C/C++程序设计本科B组决赛 ——棋子换位(代码补全题)


棋子换位

有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 }
View Code

思路:

以下为程序运行时的输出: 

初始: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)了,不然就卡死了!

    下面的几个画横线的都是这样!这种题目确实不好想,解题思路应该进行一些调整,自己按照规则尝试运行运行,在自己模拟的过程中逐步发现规律,毕竟去掉这一行以后经常进入死循环!

原文地址:https://www.cnblogs.com/zhazhaacmer/p/9041818.html