The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:

 1  2  3  4
5 6 7 8
9 10 11 12
13 14 15 x

where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

 1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->

The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and

frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three

arrangement.

InputYou will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle

1 2 3

x 4 6

7 5 8

is described by this list:

1 2 3 x 4 6 7 5 8

OutputYou will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.

Sample Input

2  3  4  1  5  x  7  6  8

Sample Output

ullddrurdllurdruldr

题意:给出8个数和一个空位(x表示),空位可以向四个方向和数交换,求最小的操作方式试其变成 (1 2 3 4 5 6 7 8 x)
思路:奇数码问题,先判断是否有解,因为是奇数码,所以有解的情况是两个情况的逆序对奇偶相同。
另外,可以把x置换成9,然后对这个9位数进行标记,可以用map<int,int>,也可以用康托展开将其和自然数一一对应。
A*的评估函数是每个位置到其应当位置的曼哈顿距离 A* + map + string路径记录:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<string.h>
#include<map>
using namespace std; struct Node
{
int cost,status;
int s[];
int pos;
int f;
string ans;
Node(int co=,int st=,int pos=,int f=,string ans=""):cost(co),status(st),pos(pos),f(f),ans(ans) {}
bool operator <(const Node x)const
{
return cost > x.cost;
}
};
map<int,int>mp;
int ways[][] = {,,-,,,,,-};
char WAYS[] = {'d','u','r','l'};
int ending;
Node start;
string ans;
int Merge(int *a,int l,int r)
{
int mid = (r+l)>>;
int i=l,j=mid+;
int b[r-l+];
int cnt = ;
int k = ;
while(i <= mid && j <= r)
{
if(a[i] <= a[j])
{
b[cnt++] = a[i++];
}
else
{
b[cnt++] = a[j++];
k += mid - i + ;
}
}
while(i <= mid)
b[cnt++] = a[i++];
while(j <= r)
b[cnt++] = a[j++];
for(int i=; i<cnt; i++)
{
a[l++] = b[i];
}
return k;
} void MER(int *a,int l,int r,int &cnt)
{
if(l >= r)
return;
int mid = (l+r)>>;
MER(a,l,mid,cnt);
MER(a,mid+,r,cnt);
cnt += Merge(a,l,r);
} int turn(int s[])
{
int cnt = ;
for(int i=; i<=; i++)
{
cnt *= ;
cnt += s[i];
}
return cnt;
} int init(char word[])
{
int a[];
for(int i=; i<=; i++)
scanf(" %c",&word[i]);
int cnt = ;
for(int i=; i<=; i++)
if((word[i]) != 'x')
a[++cnt] = word[i]-'';
int num = ;
MER(a,,cnt,num);
ending = ;
for(int i=; i<=; i++)
{
ending *= ;
ending += i;
if(word[i] == 'x')
start.s[i] = ,start.pos = i;
else
start.s[i] = word[i] - '';
}
return (num & ) == ;
} int cal(int s[])
{
int cnt = ;
for(int i=; i<=; i++)
{
if(s[i] == )
continue;
int x=(i-)/+,y=(i-)%+;
int xx=(s[i]-)/+,yy=(s[i]-)%+;
cnt += abs(x-xx)+abs(y-yy);
}
return cnt;
} bool A_bfs(Node start)
{
priority_queue<Node>que;
while(!que.empty())
que.pop();
start.status = turn(start.s);
start.f = cal(start.s);
start.cost = start.f;
que.push(start);
while(!que.empty())
{
Node tmp = que.top();
que.pop();
int status = tmp.status;
int cost = tmp.cost - tmp.f;
if(mp[status])
continue;
mp[status] = ;
if(status == ending)
{
ans = tmp.ans;
return ;
};
int x = (tmp.pos-)/+;
int y = (tmp.pos-)%+;
for(int i=; i<; i++)
{
int xx = x+ways[i][];
int yy = y+ways[i][];
if(xx < || xx > || yy < || yy > )
continue;
Node t = tmp;
t.s[(x-)*+y] = tmp.s[(xx-)*+yy];
t.s[(xx-)*+yy] = ;
t.status = turn(t.s);
t.f = cal(t.s);
t.cost = cost++t.f;
t.pos = (xx-)*+yy;
t.ans += WAYS[i];
que.push(t);
} }
return ;
} int main()
{
char word[];
while(~scanf(" %c",&word[]))
{
mp.clear();
if(init(word))
printf("unsolvable\n");
else
{
A_bfs(start);
cout << ans << endl;
}
}
}

双向bfs+康拓展开+递归路径记录(注:路径记录不能都用递归,会ME,也许姿势不对,对于从终态搜索的,因为其本身就是倒序,可以采用递推,从当前状态推过去)

#include<bits/stdc++.h>
using namespace std; struct Node
{
int cost,status;
int s[];
int pos;
Node(int co=,int st=,int pos=):cost(co),status(st),pos(pos){}
};
const int maxn = 4e5;
int fac[] = {,,,,,,,,};
int ways[][] = {,,-,,,,,-};
char WAYS[] = {'d','u','r','l'};
char FWAYS[]= {'u','d','l','r'};
char path[maxn],path2[maxn];
int pre[maxn],pre2[maxn];
bool vis[][maxn];
int ans;
queue<Node>que[];
Node start,ending;
char word[];
int a[],b[]; int cantor(int s[])
{
int sum = ;
for(int i=; i<=; i++)
{
int num = ;
for(int j=i+; j<=; j++)
{
if(s[j] < s[i])
num++;
}
sum += num*fac[-i];
}
return sum+;
} int Merge(int *a,int l,int r)
{
int mid = (r+l)>>;
int i=l,j=mid+;
int cnt = ;
int k = ;
while(i <= mid && j <= r)
{
if(a[i] <= a[j])
{
b[cnt++] = a[i++];
}
else
{
b[cnt++] = a[j++];
k += mid - i + ;
}
}
while(i <= mid)
b[cnt++] = a[i++];
while(j <= r)
b[cnt++] = a[j++];
for(int i=; i<cnt; i++)
{
a[l++] = b[i];
}
return k;
} void MER(int *a,int l,int r,int &cnt)
{
if(l >= r)
return;
int mid = (l+r)>>;
MER(a,l,mid,cnt);
MER(a,mid+,r,cnt);
cnt += Merge(a,l,r);
} int init(char word[])
{
memset(vis,,sizeof(vis));
for(int i=; i<=; i++)
scanf(" %c",&word[i]);
int cnt = ;
for(int i=; i<=; i++)
if((word[i]) != 'x')
a[++cnt] = word[i]-'';
int num = ;
MER(a,,cnt,num);
for(int i=; i<=; i++)
{
ending.s[i] = i;
if(word[i] == 'x')
start.s[i] = ,start.pos = i;
else
start.s[i] = word[i] - '';
}
start.status = cantor(start.s);
ending.status = cantor(ending.s);
ending.pos = ;
return (num & ) == ;
} bool bfs(int w)
{
int num = que[w].size();
while(num--)
{ Node tmp = que[w].front();
que[w].pop();
int status = tmp.status;
int cost = tmp.cost;
if(vis[w^][status])
{
ans = status;
return ;
}
int x = (tmp.pos-)/+;
int y = (tmp.pos-)%+;
for(int i=; i<; i++)
{
int xx = x+ways[i][];
int yy = y+ways[i][];
if(xx < || xx > || yy < || yy > )
continue;
Node t = tmp;
t.s[(x-)*+y] = tmp.s[(xx-)*+yy];
t.s[(xx-)*+yy] = ;
t.status = cantor(t.s);
if(vis[w][t.status])continue;
vis[w][t.status] = ;
t.s[(x-)*+y] = tmp.s[(xx-)*+yy];
t.s[(xx-)*+yy] = ;
t.cost = cost+;
t.pos = (xx-)*+yy;
if(w == )path[t.status] = WAYS[i],pre[t.status] = status;
else path2[t.status] = FWAYS[i],pre2[t.status] = status;
que[w].push(t);
}
}
return ;
} void out(int w)
{
if(pre[w] == -)
return;
out(pre[w]);
printf("%c",path[w]);
}
void out2(int w)
{
while(pre2[w] != -)
{
printf("%c",path2[w]);
w = pre2[w];
}
}
void solve()
{
while(!que[].empty())que[].pop();
while(!que[].empty())que[].pop();
que[].push(start);
que[].push(ending);
pre[start.status] = pre2[ending.status] = -;
vis[][start.status] = vis[][ending.status] = ;
while(!que[].empty() || !que[].empty())
{
if(bfs())
{
out(ans);
out2(ans);
puts("");
return;
}
if(bfs())
{
out(ans);
out2(ans);
puts("");
return;
}
}
} int main()
{
while(~scanf(" %c",&word[]))
{
if(init(word))
printf("unsolvable\n");
else
{
solve();
}
}
}

Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)的更多相关文章

  1. HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   Special ...

  2. HDU 1043 & POJ 1077 Eight(康托展开+BFS | IDA*)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   Special ...

  3. Eight hdu 1043 poj 1077

    Description The 15-puzzle has been around for over 100 years; even if you don't know it by that name ...

  4. poj 1077 Eight(双向bfs)

    题目链接:http://poj.org/problem?id=1077 思路分析:题目要求在找出最短的移动路径,使得从给定的状态到达最终状态. <1>搜索算法选择:由于需要找出最短的移动路 ...

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

    Eight Descriptions: 简单介绍一下八数码问题:在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8   在上图中,由于右下角位置是空的 ...

  6. POJ 1077 Eight (BFS+康托展开)详解

    本题知识点和基本代码来自<算法竞赛 入门到进阶>(作者:罗勇军 郭卫斌) 如有问题欢迎巨巨们提出 题意:八数码问题是在一个3*3的棋盘上放置编号为1~8的方块,其中有一块为控制,与空格相邻 ...

  7. cdoj 414 八数码 (双向bfs+康拓展开,A*)

    一道关乎人生完整的问题. DBFS的优越:避免了结点膨胀太多. 假设一个状态结点可以扩展m个子结点,为了简单起见,假设每个结点的扩展都是相互独立的. 分析:起始状态结点数为1,每加深一层,结点数An ...

  8. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

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

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

随机推荐

  1. Socket通讯成功案例

    Socket通讯案例 #region 服务端 //int port = 1234; //string host = "127.0.0.1"; //IPAddress ip = IP ...

  2. 银联支付java版

    注:本文来源于:<  银联支付java版    > 银联支付java版 2016年09月18日 15:55:20 阅读数:2431 首先去银联官网注册测试支付账户   下载对应的demo[ ...

  3. Python基础之递归函数与二分法

    一.递归函数 定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 我们来举个例子吧,比如:有个人问“egon”年龄,他说比“小大”大5岁,“小大”又说比“小保 ...

  4. JS:事件循环机制、调用栈以及任务队列

    点击查看原文 写在前面 js里的事件循环机制十分有趣.从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的. 在之前,我只是简单地认为由于函数执行很快,setTimeout执行 ...

  5. vue 在.vue文件里监听路由

    监听路由  watch   $route vue项目中的App.vue 文件 <template> <div id="app"> <!--includ ...

  6. (转)CSS3之pointer-events(屏蔽鼠标事件)属性说明

    我们在 HTML 开发时可能会遇到这样的情况:页面上有一些元素使用绝对定位布局,这些元素可能会遮盖住它们位置下方的某个元素的部分或者全部.默认情况下,下方元素被遮挡的部分是不会响应鼠标事件的. 但有时 ...

  7. jQuery绑定或删除绑定事件

    <!DOCTYPE html><html lang="en" class="loading"><head> <meta ...

  8. jmeter csv中获取带引号的数据详情

    最近在工作中,对jmeter实践的点滴的记录这里分享,不一定正确,仅供参考和讨论,有想法的欢迎留言.谈论. 1技巧1:从csv中获取带引号的数据详情 背景:我们从csv中获取数据,在jmeter中使用 ...

  9. Jenkins删除或替换All view

    一.Jenkins删除All view “系统管理”→“系统设置”页面,更改“Default view”的下拉选项.(前提你已经新建了新的view) 二.My Views删除All view “用户” ...

  10. The.Glory.of.Innovation 创新之路3放飞好奇

    教育最重要的就是 问题不在于教他各种学问,而在于培养他爱好学问的兴趣,而且在这种兴趣充分增长起来的时候,教他以研究学问的方法. ————  卢梭     如何辨识不同的观点, 老师考查的重点不在于学生 ...