AOJ 0121 Seven Puzzle(反向BFS+map)

卡了很久的一道题,之前用正向BFS硬缸,结果凉凉,下面是之前错误的代码,仅供自己记录,他人浏览请直接跳过:

  1 #include<cstring>
  2 #include<iostream>
  3 #include<queue>
  4 #include<algorithm>
  5 #include<cstdio>
  6
  7 using namespace std;
  8
  9 int tmaze[2][4];
 10 struct node{
 11     int maze[2][4];
 12     int x;
 13     int y;
 14     int laststep; ///1、2、3、4、0分别带表上一步走上、下、左、右(0表示初始节点)
 15     int coun; ///记录走到当前状态走了多少步
 16     node(){}
 17     node(int xi,int yi,int step,int c){
 18         x=xi;
 19         y=yi;
 20         laststep=step;
 21         coun=c;
 22         for(int i=0;i<2;i++){
 23             for(int j=0;j<4;j++)
 24                 maze[i][j]=tmaze[i][j];
 25         }
 26     }
 27 };
 28
 29 int dx[4]={1,-1,0,0};
 30 int dy[4]={0,0,-1,1};
 31 int ans;
 32 int sx,sy;
 33
 34 bool isok(){
 35     for(int i=0;i<2;i++){
 36         for(int j=0;j<4;j++)
 37             if(tmaze[i][j]!=4*i+j){
 38                 return false;
 39             }
 40     }
 41     return true;
 42 }
 43
 44 int bfs(){
 45     ans=0;
 46     queue<node> que;
 47     que.push(node(sx,sy,0,0));
 48     while(que.size()){
 49         int x=que.front().x;
 50         int y=que.front().y;
 51         int s=que.front().laststep;
 52         int c=que.front().coun;
 53         for(int i=0;i<2;i++){
 54             for(int j=0;j<4;j++){
 55                 tmaze[i][j]=que.front().maze[i][j];
 56                 printf("%d ",que.front().maze[i][j]);
 57             }
 58         }
 59         printf("\n");
 60         que.pop();
 61         if(isok()){
 62             return c;
 63         }
 64         if(x==0&&(s!=1||s==0)){ ///可以与下面的交换
 65             int t=tmaze[x][y]; tmaze[x][y]=tmaze[1][y]; tmaze[1][y]=t;
 66             que.push(node(1,y,2,c+1));
 67             t=tmaze[x][y]; tmaze[x][y]=tmaze[1][y]; tmaze[1][y]=t;
 68         }
 69         if(x==1&&(s!=2||s==0)){ ///可以与上面的交换
 70             int t=tmaze[x][y]; tmaze[x][y]=tmaze[0][y]; tmaze[0][y]=t;
 71             que.push(node(0,y,1,c+1));
 72             t=tmaze[x][y]; tmaze[x][y]=tmaze[0][y]; tmaze[0][y]=t;
 73         }
 74         if(y>0&&(s!=4||s==0)){ ///可以与左边的交换
 75             int t=tmaze[x][y]; tmaze[x][y]=tmaze[x][y-1]; tmaze[x][y-1]=t;
 76             que.push(node(x,y-1,3,c+1));
 77             t=tmaze[x][y]; tmaze[x][y]=tmaze[x][y-1]; tmaze[x][y-1]=t;
 78         }
 79         if(y<3&&(s!=3||s==0)){ ///可以与右边的交换
 80             int t=tmaze[x][y]; tmaze[x][y]=tmaze[x][y+1]; tmaze[x][y+1]=t;
 81             que.push(node(x,y+1,4,c+1));
 82             t=tmaze[x][y]; tmaze[x][y]=tmaze[x][y+1]; tmaze[x][y+1]=t;
 83         }
 84     }
 85     return 0;
 86 }
 87
 88 void solve(){
 89     for(int i=0;i<2;i++){
 90         for(int j=0;j<4;j++){
 91             scanf("%d",&tmaze[i][j]);
 92             if(tmaze[i][j]==0){
 93                 sx=i; sy=j;
 94             }
 95         }
 96     }
 97     printf("%d\n",bfs());
 98 }
 99
100 int main(){
101     solve();
102     return 0;
103 }

下面是正确代码:

有两个学习要点:1、map的使用

2、如何把读入的整形数字变成字符串

看代码:

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <map>
 5 #include <queue>
 6
 7 using namespace std;
 8
 9 map<string, int> dp;
10 int direction[4] = { 1, -1, 4, -4 };
11
12 // 让0漫游整个字符串,结果存在map中(反向bfs)
13 void bfs()
14 {
15
16     queue<string> que;
17     que.push("01234567");
18     dp["01234567"] = 0;
19     while (que.size())
20     {
21         string now = que.front(); que.pop();
22         // p是‘0‘的位置
23         int p = 0;
24         for (int j = 0; j < 8; ++j)
25         {
26             if (now[j] == ‘0‘)
27             {
28                 p = j;
29                 break;
30             }
31         }
32         for (int i = 0; i < 4; ++i)
33         {
34             int n = p + direction[i];
35             if (0 <= n && n < 8 &&
36                 !(p == 3 && i == 0) && // 右上角不能再往右了
37                 !(p == 4 && i == 1))   // 左下角不能再往左了
38             {
39                 string next = now;
40                 swap(next[p], next[n]);
41                 //这里避免的重复搜索,只有没有搜索过的状态才加入map和队列中
42                 if (dp.find(next) == dp.end())
43                 {
44                     dp[next] = dp[now] + 1;
45                     que.push(next);
46                 }
47             }
48         }
49     }
50 }
51
52
53 int main()
54 {
55     bfs();
56     string line;
57     while (getline(cin, line))
58     {
59         //读入是一个学习要点,整行读入,在把空格去掉
60         //注意remove()函数不是string类中的,是STL中的(在头文件algorithm中)
61         line.erase(remove(line.begin(), line.end(), ‘ ‘), line.end());
62         cout << dp[line] << endl;
63     }
64     return 0;
65 }

原文地址:https://www.cnblogs.com/xiaoxb17/p/11830790.html

时间: 2024-08-25 17:11:05

AOJ 0121 Seven Puzzle(反向BFS+map)的相关文章

AOJ 0121: Seven Puzzle【BFS】

From: AOJ 0121 思路:与前几题的bfs不同,这次的bfs没有明确的移动对象,看似任意一个数都可以当成对象移动.这时我们只需要抓住一个格子就行,比如我们把0作为移动对象,那么0在地图中漫游所有的格子得到的肯定就是问题的解空间.由于题目的输入是多个case,如果对每个case都运行一遍bfs就会TLE.这时我们祭出dp技能,只需要一次bfs就将解空间算出来,以后每个case只要到解空间中去找就行了. #include <iostream> #include <string>

AOJ 0121: Seven Puzzle (BFS DP STL 逆向推理)(转载)

转载自:  http://m.blog.csdn.net/blog/Enjoying_Science/42008801 题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=49880 题意:7数码问题.在2×4的棋盘上,摆有7个棋子,每个棋子上标有1至7的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格(用0表示),与空格相邻(上下左右)的棋子可以移到空格中,该棋子原先位置成为空格.给出一个初始状态(保证可以转移

poj 3221 Diamond Puzzle 反向bfs

分析: 简单的bfs,但要注意因为输入cases很多,对每个初始状态都搜一遍会超时,其实可以从终止状态反向搜一遍,对搜到的每个状态打表存下即可. 代码: //poj 3221 //sep9 #include <iostream> #include <queue> using namespace std; int n; int fac[]={1,1,2,6,24,120,720,5040,40320}; int vis[10000],g[10000]; int pos[8][8];

AOJ 0121 Seven Puzzle

7 パズル 7 パズルは 8 つの正方形のカードとこれらのカードがぴたりと収まる枠で構成されています.それぞれのカードには.互いに区別できるように 0, 1, 2, ..., 7 と番号がつけられています.枠には.縦に 2 個.横に 4 個のカードを並べることができます. 7 パズルを始めるときには.まず枠にすべてのカードを入れます.枠のなかで 0 のカードだけは.上下左右に隣接するカードと位置を交換することができます.たとえば.枠の状態が図(a) のときに.0 のカードの右に隣接した.7 のカ

AOJ 0121 Seven Puzzle {广度优先搜索}(*)

原题 题意 题意是有一个输入,比如: 1 0 2 3 4 5 6 7 摆成如下形状: 1 0 2 3 4 5 6 7 0表示空格,其他数字可以移动到0的位置.最后需要到如下形状: 0 1 2 3 4 5 6 7 上面的这种情况是需要移动一步,也就是0和1直接移动就好. 代码 #include<iostream> #include<string> #include<algorithm> #include<queue> #include<map> u

HDU 1043 Eight(反向BFS+打表+康托展开)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各个状态记录下来,因为数字太大所以用康托展开将数字离散化. 代码: 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<st

【HDU - 1043】Eight(反向bfs+康托展开)

Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的,你可以移动数字,比如可以将数字6下移一位: 1 2 3   1 2 3 4 5 6 → 4 5   7 8     7 8 6 或者将数字8右移一位: 1 2 3   1 2 3 4 5 6 → 4 5 6 7 8     7   8 1~8按顺序排列的情况称为"初始状态"(如最上方图)

UVa 1599 理想路径(反向BFS 求最短路径 )

题意: 给定一个有重边有自环的无向图,n个点(2 <= n <= 100000), m条边(1 <= m <= 200000), 每条边有一个权值, 求从第一个点到n的最少步数, 如果最少步数相同有多条路径, 那么输出权值字典序最小的一条. 分析: 用BFS解决最短路问题, 可以先从终点BFS, 求出每个点到终点的最短距离. 那么最少步数就是起点的最短距离, 最短路径就是从起点每次向最短距离比自己少1的顶点移动(如果有多个则可以随便走), 这样就可以保证走的是最短路径, 如果一开始

AOJ 0121:Seven Puzzle(bfs)

原题地址:点击打开链接 题意: 7数码问题.在2×4的棋盘上,摆有7个棋子,每个棋子上标有1至7的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格(用0表示),与空格相邻(上下左右)的棋子可以移到空格中,该棋子原先位置成为空格. 给出一个初始状态(保证可以转移到最终状态),最终状态为0 1 2 3 4 5 6 7,找出一种从初始状态转变成最终状态的移动棋子步数最少的移动步骤. 输入: 多组输入,每组8个数,表示初始状态前四个数为第一行从左到右,后四个数为第二行从左到右. 输出: 至少需要多