【9801】黑白棋游戏 - Pascal

来源:互联网 发布:无法触碰影评 知乎 编辑:程序博客网 时间:2024/05/17 13:39

题目描述

黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。

输入输出格式

输入格式:

输入文件共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。

输出格式:

输出文件的第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。

注意

本题可能有多种解法,不保证每一种解法均AC


Sample inputSample output1111
0000
1110
0010
1010
0101
1010
0101
4
1222
1424
3242
4344




解题报告:

  这道题是一道比较典型的搜索类型的题目,难度一般。

  打搜索题比较要注意的是题目类型:需不需要判重(判断是否为重复情况),以及如何判重。而本题显然是必须要经过判重这一步骤,每当黑白两种棋子对调,对调完后的棋面很可能是之前已经出现过的情况,因而需要判重。

  在选择判重方案时,这道题同时有一个比较特殊的地方:每个点只有0和1两种情况,这就很容易联想到二进制,二进制本身每一位也只有0和1两种情况。我这里采用的方法是把一张4×4的棋谱横向展开,把它变成一个16位的二进制数,因为每一个点的0、1不同,其对应的二进制数也不同,同样的把二进制转换成十进制也不同,最后加上boolean型就可以轻松判重了。 

  解决判重方案剩下的无非就是搜索,这里采用BFS(广搜)算法,用结构体(记录类型)记录第i种情况下的棋谱、步数。 

  对了,还有一个剪枝方法(应该是很容易就可以想到):想要交换的两点若颜色相同,不交换,跳到下一步。


program m9801;

type std=array[0..5,0..5] of '0'..'1';        chong=array[0..65536] of boolean;        rec=record           m:std;           step:longint;           ans:array[0..200,1..4] of 0..5;        end;const dx:array[1..2] of -1..1=(1,0);      dy:array[1..2] of -1..1=(0,1);var  i,j,k,g,h,t,zhong:longint;     s:string;     f:chong;     zan:array[0..50000] of rec;     a,b :std;function power(a,b:longint):longint;var i,j:longint;begin  j:=1;  for i:=1 to b do      j:=j*2;  exit(j);end;procedure print(pp:rec);var i,j,t:longint;begin  writeln(pp.step);  for i:=1 to pp.step do  begin    for j:=1 to 4 do      write(pp.ans[i,j]);    writeln;  end;end;function change(newf:std):longint;var i,j,tmp:longint;beginchange:=0;  for i:=1 to 4 do    for j:=1 to 4 do      begin        tmp:=ord(newf[i,j])-ord('0');        change:=change+trunc(tmp*power(2,4*(4-i)+(4-j)));      end;end;function check(newf:std):boolean;var i,j:longint;begin  for i:=1 to 4 do    for j:=1 to 4 do      if newf[i,j] <> b[i,j] then exit(false);  exit(true);end;procedure bfs;var i,j,t,x,y,tt,tmp,k,head,tail:longint;    c:char;    temp:std;    next:rec;begin   head:=0;   tail:=1;   zan[1].m:=a;   zan[1].step:=0;   f[change(a)]:=true;   repeat;     inc(head);     temp:=zan[head].m;     tmp:=zan[head].step;           for i:=1 to 4 do             for j:=1 to 4 do               for k:=1 to 2 do                  begin                    x:=i+dx[k];                    y:=j+dy[k];                    if (x>0) and (x<=4) and (y>0) and (y<=4) and (temp[i,j]<>temp[x,y]) then                       begin                          c:=temp[x,y];                          temp[x,y]:=temp[i,j];                          temp[i,j]:=c;                          tt:=change(temp);                          If not f[tt] then begin                          inc(tail);                          zan[tail].m:=temp;                          zan[tail].step:=tmp+1;                          zan[tail].ans:=zan[head].ans;                          zan[tail].ans[tmp+1,1]:=i;                          zan[tail].ans[tmp+1,2]:=j;                          zan[tail].ans[tmp+1,3]:=x;                          zan[tail].ans[tmp+1,4]:=y;                          if tt = zhong then                            begin                              print(zan[tail]);                              halt;                            end;                          F[tt]:=true;                          End;                          c:=temp[x,y];                          temp[x,y]:=temp[i,j];                          temp[i,j]:=c;                      end;                    end;  until head>tail;end;begin  fillchar(f,sizeof(f),false);  for i:=1 to 4 do    begin      readln(s);      for j:=1 to 4 do         a[i,j] :=s[j];    end;  for i:=1 to 4 do     begin       readln(s);        for j:=1 to 4 do          b[i,j]:=s[j];     end;  zhong:=change(b);  bfs;end.





1 0
原创粉丝点击