题意:给出一个八数码问题,求解法,不可解则输出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. 【BZOJ4999】This Problem Is Too Simple!(线段树)

    [BZOJ4999]This Problem Is Too Simple!(线段树) 题面 BZOJ 题解 对于每个值,维护一棵线段树就好啦 动态开点,否则空间开不下 剩下的就是很简单的问题啦 当然了 ...

  2. CF993E Nikita and Order Statistics 【fft】

    题目链接 CF993E 题解 我们记小于\(x\)的位置为\(1\),否则为\(0\) 区间由端点决定,转为两点前缀和相减 我们统计出每一种前缀和个数,记为\(A[i]\)表示值为\(i\)的位置出现 ...

  3. hdu4336 Card Collector 【最值反演】

    题目链接 hdu4336 题解 最值反演 也叫做\(min-max\)容斥,在计算期望时有奇效 \[max\{S\} = \sum\limits_{T \in S} (-1)^{|T| + 1}min ...

  4. 《Linux内核设计与实现》第18章读书笔记

    第十八章 调试 一.调试开始前的准备 1.准备开始 bug 藏匿bug的版本 相关内核代码的知识 成功调试的关键在于能否将错误重现 2.内核中的bug 其产生原因无数,表象变化也多种多样.从隐藏在源代 ...

  5. keepalived使用nc命令检测udp端口

    keepalived支持的健康检测方式有:HTTP_GET|SSL_GET.TCP_CHECK.SMTP_CHECK.MISC_CHECK. 由于keepalived自身并不支持udp检测,有TCP_ ...

  6. centos install python3 pip3

    yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-dev ...

  7. MySQL修改端口号操作

    在C盘下的program Files下找到MySQL文件夹 - my.ini配置文件有个port=3306 修改即可

  8. 开源分布式工作流任务调度系统Easy Scheduler Release 1.0.2发布

    Easy Scheduler Release 1.0.2===Easy Scheduler 1.0.2是1.x系列中的第三个版本.此版本增加了调度开放接口.worker分组(指定任务运行的机器组).任 ...

  9. 拥抱Service Fabric —— 目录

    理解分布式 经典分布式系统设计 云时代分布式系统演进 Service Fabric基础概念 Node, Application, Service, Partition/Replicas Partiti ...

  10. label和fieldset标签

    一.label标签 作用:可以通过for属性关联input标签的 id 属性,这样可以实现在点击label标签的内容时,可以使input文本框中获取输入的光标. <body> <la ...