1225 八数码难题

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题目描述 Description

Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.

问题描述

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

输入描述 Input Description

输入初试状态,一行九个数字,空格用0表示

输出描述 Output Description

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

样例输入 Sample Input

283104765

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

详见试题

分类标签 Tags

启发式搜索 广度优先搜索 深度优先搜索 迭代搜索 搜索

  1. /*赶脚这题可以状态打表o(1)查询*/
  2. /*
  3. BFS 53ms.
  4. */
  5. #include<iostream>
  6. #include<cstdio>
  7. #define N 500000
  8. using namespace std;
  9. struct node
  10. {
  11. int mp[4][4];
  12. }a[N];
  13. int g[4][4]={{0,0,0,0},{0,1,2,3},{0,8,0,4},{0,7,6,5}};
  14. int xx[4] = {0,0,1,-1};
  15. int yy[4] = {1,-1,0,0};
  16. int hash[3733800];
  17. int step[N];
  18. int h,t=1,flag;
  19. int check()
  20. {
  21. for (int i=1;i<=3;i++)
  22. for (int j=1;j<=3;j++)
  23. if (a[t].mp[i][j] != g[i][j])
  24. return 0;
  25. return 1;
  26. }
  27. int Hash()
  28. {
  29. int s = 0,k = 1;
  30. for (int i=1;i<=3;i++)
  31. for (int j=1;j<=3;j++)
  32. s += a[t].mp[i][j]*k,k*=7;
  33. s %= 3733799;
  34. if (!hash[s]) {hash[s] = 1;return 1;}
  35. return 0;
  36. }
  37. int pd(int x,int y)
  38. {
  39. if (x && x<=3 && y && y<=3) return 1;
  40. return 0;
  41. }
  42. void move(int x,int y)
  43. {
  44. for (int i=0;i<4;i++)
  45. {
  46. int p = x+xx[i], q = y+yy[i];
  47. if (pd(p,q))
  48. {
  49. for (int j=1;j<=3;j++)
  50. for (int k=1;k<=3;k++)
  51. a[t].mp[j][k] = a[h].mp[j][k];
  52. swap(a[t].mp[x][y],a[t].mp[p][q]);
  53. step[t] = step[h] +1;
  54. if (check()) {cout<<step[t]; flag = 1;return;}
  55. if (Hash()) t++;
  56. }
  57. }
  58. }
  59. void search()
  60. {
  61. while (h<t)
  62. {
  63. for (int i=1;i<=3;i++)
  64. for (int j=1;j<=3;j++)
  65. {
  66. if (a[h].mp[i][j] == 0)
  67. move(i,j);
  68. if (flag) return;
  69. }
  70. h++;
  71. }
  72. }
  73. int main()
  74. {
  75. string str;
  76. cin>>str;
  77. for (int i=1;i<=3;i++)
  78. for (int j=1;j<=3;j++)
  79. a[0].mp[i][j] = str[(i-1)*3+j-1]-'0';
  80. search();
  81. }
  1. /*
  2. 双向Bfs+map 9ms.
  3. */
  4. #include<iostream>
  5. #include<cstdio>
  6. #include<cstring>
  7. #include<map>
  8. #include<queue>
  9. using namespace std;
  10. string s=" 123804765",s1;
  11. queue<string>q;
  12. map<string,int>f,t;
  13. int bfs(){
  14. q.push(s1);q.push(s);f[s1]=1;f[s]=2;t[s1]=t[s]=0;
  15. while(!q.empty()){
  16. string x=q.front();q.pop();
  17. int p=x.find('0');
  18. if(p>=4){
  19. string k=x;int p1=p-3;//向上扩展.
  20. swap(k[p1],k[p]);
  21. if(!f[k]) f[k]=f[x],t[k]=t[x]+1,q.push(k);
  22. else if(f[k]!=f[x]) return t[k]+t[x]+1;
  23. }
  24. if(p<=6){
  25. string k=x;int p1=p+3;//向下扩展.
  26. swap(k[p1],k[p]);
  27. if(!f[k]) f[k]=f[x],t[k]=t[x]+1,q.push(k);
  28. else if(f[k]!=f[x]) return t[k]+t[x]+1;
  29. }
  30. if(p!=1&&p!=4&&p!=7){
  31. string k=x;int p1=p-1;//向左扩展.
  32. swap(k[p1],k[p]);
  33. if(!f[k]) f[k]=f[x],t[k]=t[x]+1,q.push(k);
  34. else if(f[k]!=f[x]) return t[k]+t[x]+1;
  35. }
  36. if(p!=3&&p!=6&&p!=9){
  37. string k=x;int p1=p+1;//向右扩展.
  38. swap(k[p1],k[p]);
  39. if(!f[k]) f[k]=f[x],t[k]=t[x]+1,q.push(k);
  40. else if(f[k]!=f[x]) return t[k]+t[x]+1;
  41. }
  42. }
  43. return -1;
  44. }
  45. int main()
  46. {
  47. cin>>s1;s1=" "+s1;
  48. printf("%d",bfs());
  49. return 0;
  50. }

Codevs 1225 八数码难题的更多相关文章

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

    codevs 1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description Yours和zero在研究A*启 ...

  2. codevs1225八数码难题(搜索·)

    1225 八数码难题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description Yours和zero在研究A*启 ...

  3. [luogu]P1379 八数码难题[广度优先搜索]

    八数码难题 ——!x^n+y^n=z^n 我在此只说明此题的一种用BFS的方法,因为本人也是初学,勉勉强强写了一个单向的BFS,据说最快的是IDA*(然而蒟蒻我不会…) 各位如果想用IDA*的可以看看 ...

  4. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

  5. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  6. 【洛谷P1379】八数码难题(广搜、A*)

    八数码难题 题目描述 一.广搜: 首先要考虑用什么存每一个状态 显然每个状态都用一个矩阵存是很麻烦的. 我们可以考虑将一个3*3的矩阵用一个字符串或long long 存. 每次扩展时再转化为矩阵. ...

  7. 习题:八数码难题(双向BFS)

    八数码难题(wikioi1225) [题目描述] 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出 ...

  8. 「LuoguP1379」 八数码难题(迭代加深

    [P1379]八数码难题 - 洛谷 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种 ...

  9. 洛谷——P1379 八数码难题

    P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...

随机推荐

  1. BZOJ1901 - Dynamic Rankings(树状数组套主席树)

    题目大意 给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下: Q l r k 要求你查询区间[l,r]第k小的数是哪个 C i t  要求你把第i个数修改为t 题解 动态的区间第k ...

  2. 从app里跳到appstore评论页面的实现

    // 如果要实现在应用里面跳到appstore的对应评论页面里面的话,只要将下面地址中App_ID替换成自己的id就可以了,其他的地方都不用管. // 如果要用Safari浏览器做实验的话可以将地址中 ...

  3. (贪心5.1.1)POJ 1230 Pass-Muraille

    /* * POJ_1230.cpp * * Created on: 2013年10月9日 * Author: Administrator */ #include <iostream> #i ...

  4. 校友信息管理系统&SNS互动平台之用户需求及概要设计

    前言.提纲及说明: 请移步:<校友信息管理&SNS互动平台之前言.目录及说明>(博客园地址:http://www.cnblogs.com/s6cn/p/3516876.html) ...

  5. 编程实例--for循环,找出0~100之间与8有关的正整数

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. java.util.Map按照key值合并的value的Collection 集合中。

    用java实现把多个map的内容合并的一个resultMap中 代码大致如下 /**  * @author Shalf  */ public class MapUtil { /** * 把partMa ...

  7. freemarker list (长度,遍历,下标,嵌套,排序)

    1. freemarker获取list的size : Java ArrayList<String> list = new ArrayList<String>(); Freema ...

  8. 【转】Android应用开发性能优化完全分析

    http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关 ...

  9. C#中多线程 委托的使用

    背景:  什么是多线程?我们在建立以个C#项目时,往往会在Form1上添加控件,然后写代码,初 学者都是在重复这个过程,其实这个过程是单线程的,可以理解为只有“main”主线程,有 的时候往往需要同时 ...

  10. RHCA442学习笔记-Unit10内存地址及分配

      Unit 10 Memory Addressing and Allocation 内存地址及分配 学习目标: A. 虚拟地址与物理地 B. 调整内存地址分配 C. 解析内存溢出    10.1 O ...