【问题描述】

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

【样例输入】

1111

0000

1110

0010

1010

0101

1010

0101

【样例输出】

4

1222

1424

3242

4344

【解题思路】

看到最少步数,果断广搜。不过状态太多,需要判重。大家可以看到,出题人在数据一栏写了必须用状态压缩,不能用康托展开和hash,他说往东走,咱们偏往西走,就用hash优化。(别想从我嘴里套出我不会状态压缩和康托展开)不过hash函数会很不好找,这里我用的是二进制转十进制的方法存hash,这样的话保证每种状态下只有一个hash函数,就不需要挂链表了,主要的是比较目前状态与目标状态是否相同时会耗费点时间,不过1s还是能过的,然后一个关键的地方就是存储哪两个坐标换了位置,我是用的字符来存的,详见代码。

【代码实现】

 type arr=array[..,..] of char;
rec=record
m:arr;
step:longint;
ans:array[..,..] of char;
end;
const dx:array[..] of longint=(,-,,);
dy:array[..] of longint=(,,-,);
var start,ans:rec;
f:array[..] of boolean;
spos,epos:arr;
fr,r,i,j:longint;
a:array[..] of rec;
function equal(m:arr):boolean;
var i,j:longint;
begin
for i:= to do
for j:= to do
if m[i,j]<>epos[i,j] then exit(false);
exit(true);
end;
function hash(m:arr):longint;//二进制转十进制,用位运算,效率高
var res,i,j:longint;
begin
res:=;
for i:= to do
for j:= to do
begin
res:=(res shl );
res:=res+ord(m[i,j])-ord('');
end;
exit(res);
end;
procedure bfs;
var t,i,j,k,x,y:longint;
now,next:rec;
temp:char;
begin
fillchar(f,sizeof(f),true);
t:=hash(spos);
f[t]:=false;
fr:=;r:=;
while fr<>r do
begin
inc(fr);
now:=a[fr];
if equal(now.m) then
begin
ans:=now;
exit;
end;
for i:= to do
for j:= to do
for k:= to do
begin
next:=now;
inc(next.step);
x:=i+dx[k];
y:=j+dy[k];
if (x>=)and(x<=)and(y>=)and(y<=) then
begin
temp:=next.m[i,j];
next.m[i,j]:=next.m[x,y];
next.m[x,y]:=temp;
next.ans[next.step,]:=chr(ord('')+i);
next.ans[next.step,]:=chr(ord('')+j);
next.ans[next.step,]:=chr(ord('')+x);
next.ans[next.step,]:=chr(ord('')+y);
next.ans[next.step,]:=#;//存储哪两个坐标换了位置
if equal(next.m) then
begin
ans:=next;
exit;
end;
t:=hash(next.m);
if f[t] then
begin
f[t]:=false;
inc(r);
a[r]:=next;
end;
end;
end;
end;
end;
begin
for i:= to do
begin
for j:= to do
read(spos[i,j]);
readln;
end;
for i:= to do
begin
for j:= to do
read(epos[i,j]);
readln;
end;
for i:= to do
for j:= to do
start.m[i,j]:=spos[i,j];
start.step:=;
a[]:=start;
bfs;
writeln(ans.step);
for i:= to ans.step do
begin
for j:= to do
write(ans.ans[i,j]);
writeln;
end;
end.

黑白棋游戏 (codevs 2743)题解的更多相关文章

  1. 用Dart写的黑白棋游戏

    2013年11月,Dart语言1.0稳定版SDK发布,普天同庆.从此,网页编程不再纠结了. 在我看来,Dart语法简直就是C#的升级版,太像了.之所以喜欢Ruby的一个重要理由是支持mixin功能,而 ...

  2. [CareerCup] 8.8 Othello Game 黑白棋游戏

    8.8 Othello is played as follows: Each Othello piece is white on one side and black on the other. Wh ...

  3. 洛谷 题解 P1225 【黑白棋游戏】

    看见很多dalao写了什么双向BFS,蒟蒻表示不会写啊. 怎么办办? 先来分析一下题目,一眼看去就是一个搜索题,考虑DFS与BFS. 先放一份DFS的代码: #include<bits/stdc ...

  4. BZOJ2319 : 黑白棋游戏

    将01串按1分段,那么分析可得长度为$a$的段拼上长度为$b$的段的SG值为$a-[a\leq b]$. 设$f[i][j][k][l]$表示从后往前用了$i$个1,$j$个0,当前段长度为$k$,后 ...

  5. 洛谷 - P1225 - 黑白棋游戏 - bfs

    神奇bug,没有记录pre就show了,找了1个小时. #include <bits/stdc++.h> using namespace std; #define ll long long ...

  6. Bzoj 2281 [Sdoi2011]黑白棋 题解

    2281: [Sdoi2011]黑白棋 Time Limit: 3 Sec  Memory Limit: 512 MBSubmit: 592  Solved: 362[Submit][Status][ ...

  7. BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)

    题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...

  8. 【BZOJ2281】[SDOI2011]黑白棋(博弈论,动态规划)

    [BZOJ2281][SDOI2011]黑白棋(博弈论,动态规划) 题面 BZOJ 洛谷 题解 先看懂这题目在干什么. 首先BZOJ上面的题面没有图,换到洛谷看题就有图了. 不难发现都相邻的两个异色棋 ...

  9. bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)

    黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...

随机推荐

  1. 程序员必备:Oracle日常维护命令

        上一篇讲了Linux的日常维护命令,这篇讲讲Oracle的日常维护命令.工作中需要使用Oracle数据库的童鞋们,相信或多或少都需要对Oracle做一些基本的维护操作,例如导入导出总该有吧?( ...

  2. 在页面中使用Eval的两种方案

    ①直接取<%#Eval("name")%> ②进行运算<%#Convert.ToInt32(Eval("count"))-(Eval(&quo ...

  3. C#将C++动态库的回调函数封装成事件

    关于C#调用C++动态库的文章很多,调用动态库中回调函数的方法也不在少数.但大多数调用回调函数的方法依然保留了C++的语法特点. 比如有一段C++的回调函数代码,为了表达它的意思,我把注释也粘贴了进来 ...

  4. 【Unity Shaders】学习笔记——SurfaceShader(十)镜面反射

    [Unity Shaders]学习笔记——SurfaceShader(十)镜面反射 如果你想从零开始学习Unity Shader,那么你可以看看本系列的文章入门,你只需要稍微有点编程的概念就可以. 水 ...

  5. Android开发-API指南-创建 Content Provider

    Creating a Content Provider 英文原文:http://developer.android.com/guide/topics/providers/content-provide ...

  6. yii中第三方库

    yii中存在一些路径别名:ext:表示包含了所有第三方扩展的目录  参考:http://www.yiiframework.com/doc/guide/1.1/zh_cn/basics.namespac ...

  7. android Tab =viewpager+fragmnet

    1.定义几个fragment 的subclass 如fragmentone,fragmenttwo; public class fragmentthree extends Fragment { pri ...

  8. Linux:一台apache服务器上部署多个项目的apache配置

    第一步: 将代码取到/var/www/html目录下(此为默认目录,具体看apache的设置):该目录下可以放多个项目,如: [root@www html]# pwd/var/www/html[roo ...

  9. leetcode 66

    66. Plus One Given a non-negative number represented as an array of digits, plus one to the number. ...

  10. trap在shell中捕捉信号

    一.trap捕捉到信号之后,可以有三种反应方式:(1)执行一段程序来处理这一信号(2)接受信号的默认操作(3)忽视这一信号 二.trap对上面三种方式提供了三种基本形式:第一种形式的trap命令在sh ...