题意:给出一个八数码问题,求解法,不可解则输出unsolvable。

分析:可以用ida*算法,估价函数可以使用每个数码到其最终位置的最短距离之和。对于不可解的判断,我这里用迭代深度大于100时判定为不可解。

还有一种更高级的无解判断方法。就是将八数码矩阵中的空格忽略,然后将8个数字排成一排,第二行接在第一行后面,第三行接在第二行后面,通过观察我们发现移动空格不会影响这个8个数字组成的数列中逆序数队的奇偶性,因此如果逆序数对的奇偶性与目标状态不同则一定无解。至于为什么奇偶性相同就一定有解,我就不知道为什么了,不过这个命题确实是正确的。

可以将这种方法做适当修改并推广至15数码问题。

#include <iostream>
#include <stack>
#include <cmath>
using namespace std; const int maxn = ; char ans[];
int tot, dir[][] = {{-,},{,},{,},{,-}}; struct Node
{
char map[maxn];
int g, move, xpos;
}starts; void init()
{
for (int i = ; i < ; i++)
{
starts.map[i] = ' ';
while (starts.map[i] == ' ')
scanf("%c",&starts.map[i]);
if (starts.map[i] == 'x')
{
starts.map[i] = ;
starts.xpos = i;
} else
starts.map[i] -= '';
}
} int h(Node &a)
{
int x1, x2, y1, y2, i, r = ; for (i = ; i < ; i++)
{
x1 = i / ;
y1 = i % ;
x2 = (a.map[i] - ) / ;
y2 = (a.map[i] - ) % ;
r += abs(x1 - x2) + abs(y1 - y2);
}
return r;
} Node getchild(int a, Node &currents)
{
int x, y, pos, i;
Node r; x = currents.xpos / + dir[a][];
y = currents.xpos % + dir[a][];
r.xpos = -;
if (x < || y < || x > || y > )
return r;
pos = x * + y;
r.xpos = pos;
r.g = currents.g + ;
r.move = a;
for (i = ; i < ; i++)
r.map[i] = currents.map[i];
r.map[pos] = ;
r.map[currents.xpos] = currents.map[pos];
return r;
} bool ida()
{
int pathlimit, i, temp, next;
bool success = ;
Node currents, child; next = h(starts)/;
stack<Node> stk;
do
{
pathlimit = next;
if (pathlimit > )
return false;
tot = ;
starts.g = ;
starts.move = -;
next = ;
stk.push(starts);
do
{
currents = stk.top();
ans[currents.g] = currents.move;
stk.pop();
temp = h(currents);
if (temp == )
{
tot = currents.g;
success = true;
}
else if (pathlimit >= currents.g + temp / )
{
for (i = ; i < ; i++)
{
child = getchild(i, currents);
if (child.xpos != - && abs(child.move - currents.move) != )
stk.push(child);
}
}else if (next > currents.g + temp / )
next = currents.g + temp / ;
}while (!success && !stk.empty());
}while (!success);
return true;
} void print()
{
int i; for (i = ; i <= tot; i++)
switch(ans[i])
{
case : printf("u"); break;
case : printf("r"); break;
case : printf("d"); break;
case : printf("l"); break;
}
printf("\n");
} int main()
{
//freopen("t.txt", "r", stdin);
init();
if (ida())
print();
else
printf("unsolvable\n");
return ;
}

poj1077的更多相关文章

  1. ACM/ICPC 之 BFS-广搜进阶-八数码(经典)(POJ1077+HDU1043)

    八数码问题也称为九宫问题.(本想查查历史,结果发现居然没有词条= =,所谓的历史也就不了了之了) 在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个 ...

  2. POJ-1077 HDU 1043 HDU 3567 Eight (BFS预处理+康拓展开)

    思路: 这三个题是一个比一个令人纠结呀. POJ-1077 爆搜可以过,94ms,注意不能用map就是了. #include<iostream> #include<stack> ...

  3. POJ1077 Eight —— 经典的搜索问题

    题目链接:http://poj.org/problem?id=1077 Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submission ...

  4. poj1077 Eight【爆搜+Hash(脸题-_-b)】

    转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4298840.html   ---by 墨染之樱花 题目链接:http://poj.org/pr ...

  5. POJ1077&&HDU1043(八数码,IDA*+曼哈顿距离)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30127   Accepted: 13108   Special ...

  6. poj1077(康托展开+bfs+记忆路径)

    题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如: 1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案.可以右移r,左移l,上移u,下移dx 4 6 4 5 67 ...

  7. POJ1077 Eight A*

    这个题扔到A*可也还行... 定义估价函数h():为每个数或空格的位置 到 最终状态中所在位置 的 曼哈顿距离 的 总和. 把状态压成一个九进制数,便于存储和判重. 然后记录方案可以记录一下此次的操作 ...

  8. POJ1077 八数码 BFS

    BFS 几天的超时... A*算法不会,哪天再看去了. /* 倒搜超时, 改成顺序搜超时 然后把记录路径改成只记录当前点的操作,把上次的位置记录下AC..不完整的人生啊 */ #include < ...

  9. POJ1077 Eight —— IDA*算法

    主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html 代码一:像BFS那样,把棋盘数组放在结构体中. #include <iostream&g ...

随机推荐

  1. 搭建ELK收集Nginx日志

    众所周知,ELK是日志收集套装,这里就不多做介绍了. 画了一个粗略的架构图,如下: 这里实际用了三个节点,系统版本为CentOS6.6,ES版本为2.3.5,logstash版本为2.4.0,kiba ...

  2. 控制对象的创建方式(禁止创建栈对象or堆对象)和创建的数量

    我们知道,C++将内存划分为三个逻辑区域:堆.栈和静态存储区.既然如此,我称位于它们之中的对象分别为堆对象,栈对象以及静态对象.通常情况下,对象创建在堆上还是在栈上,创建多少个,这都是没有限制的.但是 ...

  3. hadoop进阶----hadoop经验(一)-----生产环境hadoop部署在超大内存服务器的虚拟机集群上vs几个内存较小的物理机

    生产环境 hadoop部署在超大内存服务器的虚拟机集群上 好 还是  几个内存较小的物理机上好? 虚拟机集群优点 虚拟化会带来一些其他方面的功能. 资源隔离.有些集群是专用的,比如给你三台设备只跑一个 ...

  4. Java考试题之八

    QUESTION 139 Giventhe following directory structure: bigProject |--source | |--Utils.java ||--classe ...

  5. git 利用hook 实现服务器自动更新代码

    如何利用git的hook实现提交代码后自动更新? 因为个人开发经常需要提交代码,每次都需要连接服务器去pull代码,重启服务器就显得十分繁琐,因此github提供了一个时间钩子,用户push代码后可以 ...

  6. 实验三:将读取数据功能从Repository中分离

    先理解下面这段话之后再开始做实验 经过实验二的改造之后,我们代码有一点结构的概念了: Listing.aspx:向Repository要Products,然后将得到的Products在页面中显示出来. ...

  7. 获取异常信息e.printStackTrace()的内容

    获取异常信息e.printStackTrace()的内容 最近做项目的时候需要记录操作的日志,但是记录异常信息的是发现使用e.getMessage()根本无法满足需要,并且e.getMessage() ...

  8. JS中的getter与setter

    一.什么是getter和setter getter 是一种获得属性值的方法,setter是一种设置属性值的方法 getter负责查询值,它不带任何参数,setter则负责设置键值,值是以参数的形式传递 ...

  9. 基本UDP套接字编程

    概述 使用TCP编写的应用程序和使用UDP编写的应用程序之间存在一些本质差异,其原因在于这两个传输层之间的差别:UDP是无连接不可靠的数据报协议,非常不同于TCP提供的面向连接的可靠字节流.然而相比T ...

  10. hive架构原理简析-mapreduce部分

    整个处理流程包括主要包括,语法解析(抽象语法树,AST,采用antlr),语义分析(sematic Analyzer生成查询块),逻辑计划生成(OP tree),逻辑计划优化,物理计划生成(Task ...