八数码难题 (codevs 1225)题解

【问题描述】

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

【样例输入】

283104765

【样例输出】

4

【解题思路】

这题要求最少步数,因此为广度优先搜索,用队列实现。最简单的方法就是直接将每种状态存入3×3的数组中,然后将空格往四个方向移动,直至目标状态。

不过,让我们来看一看样例。

按往常来说,如果是存入3×3的数组中,那么样例中应该是2 8 3

1 0 4

7 6 5

可是,样例却是一串数字,且中间没有空格,那么,这就给了我们一种思路,以字符串的形式存入,然后搜索,与目标状态比较时也方便一些。那么我们就换成字符串来搜索,但是字符串中要注意一下,第三位不能移到第四位,第四位不能移到第三位,因此,我们需要对该数字进行判断,看它属于哪一列,然后再搜索。

不过,这两种方式都会超时(在输出结果的步数比较大的时候),因此,我们需要判重,然而,直接开一个12345678-876543210的布尔型数组会超时,所以,这里我们用到了哈希优化。

【代码实现】

  1 type rec=record
  2      s:string;
  3      s1,dep:longint;
  4 end;
  5 const di:array[1..4] of longint=(-1,-3,3,1);
  6       c:string=‘123804765‘;
  7 var a:array[1..100000] of rec;
  8     b:string;
  9     f,r,i,j,k,x:longint;
 10     flag:array[1..1000010] of boolean;
 11 procedure bfs;
 12 var si:char;
 13     i,j,k:longint;
 14 begin
 15  while f<r do
 16   begin
 17    inc(f);
 18    case a[f].s1 of//判断数字属于哪一列
 19     2,5,8:
 20      for i:=1 to 4 do
 21       if (a[f].s1+di[i]>=1)and(a[f].s1+di[i]<=9) then
 22        begin
 23         inc(r);
 24         a[r]:=a[f];
 25         a[r].s[a[r].s1]:=a[r].s[a[r].s1+di[i]];
 26         a[r].s[a[r].s1+di[i]]:=‘0‘;
 27         a[r].s1:=a[r].s1+di[i];
 28         inc(a[r].dep);
 29         val(a[r].s,x);
 30         if not(flag[x mod 1000009]) then
 31          dec(r)
 32         else
 33          begin
 34           flag[x mod 1000009]:=false;
 35           if a[r].s=c then
 36            begin
 37             writeln(a[r].dep);
 38             halt;
 39            end;
 40          end;
 41        end;
 42     1,4,7:
 43      for i:=2 to 4 do
 44       if (a[f].s1+di[i]>=1)and(a[f].s1+di[i]<=9) then
 45        begin
 46         inc(r);
 47         a[r]:=a[f];
 48         a[r].s[a[r].s1]:=a[r].s[a[r].s1+di[i]];
 49         a[r].s[a[r].s1+di[i]]:=‘0‘;
 50         a[r].s1:=a[r].s1+di[i];
 51         inc(a[r].dep);
 52         val(a[r].s,x);
 53         if not(flag[x mod 1000009]) then
 54          dec(r)
 55         else
 56          begin
 57           flag[x mod 1000009]:=false;
 58           if a[r].s=c then
 59            begin
 60             writeln(a[r].dep);
 61             halt;
 62            end;
 63          end;
 64        end;
 65     3,6,9:
 66      for i:=1 to 3 do
 67       if (a[f].s1+di[i]>=1)and(a[f].s1+di[i]<=9) then
 68        begin
 69         inc(r);
 70         a[r]:=a[f];
 71         a[r].s[a[r].s1]:=a[r].s[a[r].s1+di[i]];
 72         a[r].s[a[r].s1+di[i]]:=‘0‘;
 73         a[r].s1:=a[r].s1+di[i];
 74         inc(a[r].dep);
 75         val(a[r].s,x);
 76         if not(flag[x mod 1000009]) then
 77          dec(r)
 78         else
 79          begin
 80           flag[x mod 1000009]:=false;
 81           if a[r].s=c then
 82            begin
 83             writeln(a[r].dep);
 84             halt;
 85            end;
 86          end;
 87        end;
 88     end;
 89   end;
 90 end;
 91 begin
 92  fillchar(flag,sizeof(flag),true);
 93  readln(a[1].s);
 94  for i:=1 to 9 do
 95   if a[1].s[i]=‘0‘ then
 96    begin
 97     a[1].s1:=i;
 98     break;
 99    end;
100  f:=0;r:=1;
101  bfs;
102 end.
时间: 2024-09-28 04:41:54

八数码难题 (codevs 1225)题解的相关文章

双向广搜+hash+康托展开 codevs 1225 八数码难题

codevs 1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找

1225 八数码难题

1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765

wikioi 1225 八数码难题 IDA*

为什么就是跑不出0ms 八数码0.0,我又来水博客了. IDA*算法,A*为曼哈顿距离,判重用康拓展开. #include<cstring> #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> using namespace std; int a[4][4]; int dx[]={0,0,-1,1}; int dy[]={-1,1,0,0}; char s

codevs1225八数码难题(搜索&#183;)

1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最

洛谷【P1379】八数码难题

P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入输出格式 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊

洛谷OJ P1379 八数码难题 解题报告

洛谷OJ P1379 八数码难题 解题报告 by MedalPluS 题目描述   在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变.   输入格式   输入初试状态,一行九个数字,空格用0表示   输出格式 只有一行,该行只有一个数字,表示从初始状态到

洛谷 P1379 八数码难题

P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入输出格式 输入格式: 输入初始状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊

luogu_1379 八数码难题

八数码-->BFS+set 1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<set> 6 using namespace std; 7 struct aaa{ 8 int map[4][4]; 9 int dep,x,y; 10 }que[370000]; 11 set<int> ssr; 12

codevs 1225:八数码难题【双向广搜】

这里是传送门 这道题用普通BFS是可以做的,但是很明显没得过,效率太低了.效率更高的算法A*和双向广搜都可取,这写一下双向广搜的. 注意题目中的判重很重要,可以转化成九位数用hash来解决这个问题. #include <set> #include <string> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define