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<string>
 6 #include<queue>
 7 using namespace std;
 8 typedef long long ll;
 9 const int N=4e5+5;
10
11 int vis[N];
12 string path[N];
13 char map[15];
14 char index[5]="udrl";//因为是逆向所以方向要反一下
15 int d[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
16 int fac[15]={1,1,2,6,24,120,720,5040,40320};
17
18 struct node{
19     char num[10];
20     int pos;
21     string path;
22 }pre,now;
23
24 //求康托展开值
25 int cantor(char s[]){
26     int sum=0;
27     int n=strlen(s);
28     for(int i=0;i<n;i++){
29         int cnt=0;
30         for(int j=i+1;j<n;j++){
31             if(s[i]>s[j])
32                 cnt++;
33         }
34         sum+=cnt*fac[n-i-1];
35     }
36     return sum+1;
37 }
38 //从12345678x逆向BFS打表
39 void bfs(){
40     queue<node>q;
41     now.pos=8;
42     for(int i=0;i<8;i++)
43         now.num[i]=i+1+‘0‘;
44     now.num[8]=‘0‘;
45     now.num[9]=‘\0‘;
46     q.push(now);
47     while(!q.empty()){
48         pre=q.front();
49         q.pop();
50         int pos=pre.pos;
51         //转换成二维坐标
52         int x=pos/3;
53         int y=pos%3;
54         for(int i=0;i<4;i++){
55             int xx=x+d[i][0];
56             int yy=y+d[i][1];
57             if(xx<0||yy<0||xx>2||yy>2)
58                 continue;
59             //转换回一维坐标
60             int new_pos=xx*3+yy;
61             now=pre;
62             swap(now.num[pos],now.num[new_pos]);
63             int tmp=cantor(now.num);
64             if(!vis[tmp]){
65                 now.pos=new_pos;
66                 //index[i]要加在前面,反的嘛
67                 now.path=index[i]+now.path;
68                 vis[tmp]=1;
69                 //存储路径
70                 path[tmp]=now.path;
71                 q.push(now);
72             }
73         }
74     }
75 }
76
77 int main(){
78     char c;
79     bfs();
80     while(cin>>c){
81         //x转换成0便于康托展开
82         if(c==‘x‘)
83             map[0]=‘0‘;
84         else
85             map[0]=c;
86         for(int i=1;i<9;i++){
87             cin>>map[i];
88             if(map[i]==‘x‘)
89                 map[i]=‘0‘;
90         }
91         int aim=cantor(map);
92         if(vis[aim])
93             cout<<path[aim]<<endl;
94         else
95             cout<<"unsolvable"<<endl;
96     }
97 }
时间: 2024-08-05 06:47:34

HDU 1043 Eight(反向BFS+打表+康托展开)的相关文章

HDU1430 BFS + 打表 + 康托展开

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 , 一道比较好的题. 这道题要用到很多知识,康托展开.BFS.打表的预处理还要用到一一映射,做完受益匪浅. 其实这道题也可以用双向BFS来写,思路也已经有了,过几天再来写. 本文持续更新. 先说搜索部分: 对于魔板的每一个状态,都可以进行A.B.C三种操作,所以按照图论来讲,就是操作前的状态可以到达操作后的状态,所以就这样转换成了广搜问题. 这里要注意一点,由于题目要求字典序最小的,所以搜索的

HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3

http://acm.hdu.edu.cn/showproblem.php?pid=3567 相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过,而且也不好控制字典序 换个角度想,虽然起始状态有很多,但是到底哪一位是1,哪一位是2不是最重要的,最重要的是和目标状态对应,所以可以把起始状态重新编码为"12345678"这种形式(先不考虑X),然后目标状态也对应过去,当考虑X的时候,我们可以认为起始状态只有9种,分别是'X'在各个位置的

HDU 1043 Eight (BFS&#183;八数码&#183;康托展开)

题意  输出八数码问题从给定状态到12345678x的路径 用康托展开将排列对应为整数  即这个排列在所有排列中的字典序  然后就是基础的BFS了 #include <bits/stdc++.h> using namespace std; const int N = 5e5, M = 9; int x[4] = { -1, 1, 0, 0}; int y[4] = {0, 0, -1, 1}; int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320

hdoj1043 Eight(逆向BFS+打表+康拓展开)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 思路: 由于自己对康拓展开用的太少,看到这个题没想到康拓展开,最开始打算直接转换为数字,但太占内存了,又想到可以将状态存进set,后来查了一下发现原来是考察康拓展开.另外就是需要打表预处理,这样快很多.BFS部分就是已知终点,从终点逆向搜索,并存每个状态的上一个状态以及操作,以便输出. 坑点:输入是多组输入,POJ那道题才是一组输入,卡在这一上午T_T. 有一组输入为12345678x,需要特

HDU 1430 魔板(康托展开+BFS+预处理)

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2921    Accepted Submission(s): 649 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜

【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按顺序排列的情况称为"初始状态"(如最上方图)

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

HDU 1043 Eight(双向BFS+康托展开)

http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用双向BFS来做. ①双向BFS 在单向BFS的基础上,多建一个从终止状态开始搜索的队列,当然这个时候需要两个vis[]辅助数组,分别记录两个队列的访问情况,当两个队列相遇时即可终止循环. ②康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[

hdu 1043 Eight(康托展开,打表)

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef long long LL; 5 6 /** 7 学习:(1)康托展开的使用 8 (2)路径记录 9 ? A* 10 ? 双向bfs 11 */ 12 13 int t[9],s[9]; 14 bool vis[362880 + 10]; 15 char ans[362880 + 10][42]; 16 int fac[]={1,1