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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043

思路:

由于自己对康拓展开用的太少,看到这个题没想到康拓展开,最开始打算直接转换为数字,但太占内存了,又想到可以将状态存进set,后来查了一下发现原来是考察康拓展开。另外就是需要打表预处理,这样快很多。BFS部分就是已知终点,从终点逆向搜索,并存每个状态的上一个状态以及操作,以便输出。

坑点:输入是多组输入,POJ那道题才是一组输入,卡在这一上午T_T。

   有一组输入为12345678x,需要特殊处理,不能不输出,可以输出“lr”。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3
 4 const int maxn=1e6+5;
 5 struct node{
 6     char a[9];
 7     int x,y;
 8     int cnt;
 9 }tmp;
10
11 int fac[9];
12 int vis[maxn];
13 char path[maxn];
14 int pre[maxn];
15 int go[4][2]={-1,0,0,1,1,0,0,-1};
16
17 void init(){
18     fac[0]=fac[1]=1;
19     for(int i=2;i<9;i++) fac[i]=fac[i-1]*i;
20 }
21
22 int cantour(char *s){
23     int ans=0,k;
24     for(int i=0;i<8;i++){
25         k=0;
26         for(int j=i+1;j<9;j++)
27             if(s[j]<s[i]) k++;
28         ans+=k*fac[8-i];
29     }
30     return ans;
31 }
32
33 void bfs(){
34     queue<node> q;
35     for(int i=0;i<8;i++)
36         tmp.a[i]=i+1+‘0‘;
37     tmp.a[8]=‘0‘;
38     tmp.x=2,tmp.y=2,tmp.cnt=cantour(tmp.a);
39     vis[tmp.cnt]=1;
40     q.push(tmp);
41     path[tmp.cnt]=-1;
42     while(!q.empty()){
43         node now=q.front();q.pop();
44         int nx=now.x,ny=now.y,ncnt=now.cnt;
45         for(int i=0;i<4;i++){
46             int xx=nx+go[i][0],yy=ny+go[i][1];
47             if(xx<0||xx>2||yy<0||yy>2) continue;
48             strcpy(tmp.a,now.a);
49             swap(tmp.a[nx*3+ny],tmp.a[xx*3+yy]);
50             tmp.x=xx,tmp.y=yy,tmp.cnt=cantour(tmp.a);
51             if(!vis[tmp.cnt]){
52                 vis[tmp.cnt]=1;
53                 pre[tmp.cnt]=ncnt;
54                 if(i==0) path[tmp.cnt]=‘d‘;
55                 else if(i==1) path[tmp.cnt]=‘l‘;
56                 else if(i==2) path[tmp.cnt]=‘u‘;
57                 else path[tmp.cnt]=‘r‘;
58                 q.push(tmp);
59             }
60         }
61     }
62 }
63
64 void print(int f){
65     while(path[f]!=-1){
66         printf("%c",path[f]);
67         f=pre[f];
68     }
69     printf("\n");
70 }
71
72 int main(){
73     char c[9],ch;
74     int f;
75     init();
76     bfs();
77     while(scanf(" %c",&ch)!=EOF){
78         if(ch==‘x‘) c[0]=‘0‘;
79         else c[0]=ch;
80         for(int i=1;i<9;i++){
81             scanf(" %c",&ch);
82             if(ch==‘x‘) c[i]=‘0‘;
83             else c[i]=ch;
84         }
85         f=cantour(c);
86         if(path[f]==-1) printf("lr\n");
87         else if(!vis[f]) printf("unsolvable\n");
88         else print(f);
89     }
90     return 0;
91 }

原文地址:https://www.cnblogs.com/FrankChen831X/p/10357366.html

时间: 2024-10-10 08:57:08

hdoj1043 Eight(逆向BFS+打表+康拓展开)的相关文章

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】+【康拓展开】

<题目链接> 题目大意:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 解题分析:本题用BFS来寻找路径,为了降低复杂度,用BFS从最终的目标状态开始处理,将所有搜索到状态以及对应的路径打表记录,然后对于输入的矩阵,直接查表输出答案 即可,本题还有一个难点,就是如何判断记录已经搜索过的状态,如果使用map+string(矩阵看成一维)会超时,所以我们这里用康拓展开式来记录状态. #include<cstdio

HDU1430 BFS + 打表 + 康托展开

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

Hdoj 1430 魔板 【BFS】+【康拓展开】+【预处理】

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

ACM/ICPC 之 BFS(离线)+康拓展开 (HDU1430-魔板)

魔板问题,一道经典的康拓展开+BFS问题,为了实现方便,我用string类来表示字符串,此前很少用string类(因为不够高效,而且相对来说我对char数组的相关函数比较熟),所以在这里也发现了很多容易被忽视的问题. 对于康拓展开不太熟系的可以先参看一篇博客:http://blog.csdn.net/zhongkeli/article/details/6966805 关于sting类,大家要注意,在赋值的时候,其赋值位置不能与首位置间存在未赋值部分. 题目需要转换思路的地方是: 我们需要将起始魔

九宫重拍(bfs + 康拓展开)

问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12345678. 把第二个图的局面记为:123.46758 显然是按从上到下,从左到右的顺序记录数字,空格记为句点. 本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达.如果无论多少步都无法到达,则输出-1. 输入格式 输入第一行包含九宫的初态,第二行包含九宫的终态. 输出格式 输出最

UVA 10085(bfs+康拓展开)八数码问题

Description Problem A The Most Distant State Input: standard input Output: standard output The 8-puzzle is a square tray in which eight square tiles are placed. The remaining ninth square is uncovered. Each tile has a number on it. A tile that is adj

【HDOJ3567】【预处理bfs+映射+康拓展开hash】

http://acm.hdu.edu.cn/showproblem.php?pid=3567 Eight II Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 130000/65536 K (Java/Others)Total Submission(s): 4541    Accepted Submission(s): 990 Problem Description Eight-puzzle, which is also calle

九宫重排_康拓展开_bfs

历届试题 九宫重排 时间限制:1.0s   内存限制:256.0MB 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12345678. 把第二个图的局面记为:123.46758 显然是按从上到下,从左到右的顺序记录数字,空格记为句点. 本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达.如果无论多少步都无法到达,则输出-1. 输入格