HDOJ 1043 Eight(A* 搜索)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043
思路分析:
<1> 搜索算法: A*算法, Heuristic函数:曼哈顿距离
<2> 剪枝技巧: 如果8数码问题中的初始状态的逆序数为奇数(除了’x’),则不存在解;否则,存在解;
代码如下:
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; const int MAX_N = + ;
int map[];
bool close[MAX_N];
char dir[MAX_N], direction[] = "udlr";
int open[MAX_N], pa[MAX_N], f[MAX_N];
const int FACT[] = {, , , , , , , , };
const int MOVE[][] = {{, -}, {, }, {-, }, {, }}; struct Node
{
int id;
int f, g, h;
int flags; // 表示该状态被松弛次数
Node() {}
Node(int a_id, int a_g, int a_h, int a_flags)
{
id = a_id, g = a_g, h = a_h, flags = a_flags;
f = g + h;
}
friend bool operator<(const Node &lhs, const Node &rhs);
};
bool operator<(const Node &lhs, const Node &rhs) { return lhs.f > rhs.f; }
priority_queue<Node> find_min; int StateToCanto()
{
int state_num = ;
for (int i = ; i < ; ++i)
{
int temp = map[i] - ; for (int j = ; j < i; ++j)
temp -= (map[j] < map[i]);
state_num += temp * FACT[ - i];
}
return state_num;
} int StateToId()
{
int ans = ; for (int i = ; i < ; ++i)
ans = ans * + map[i];
return ans;
} void IdToState(int num)
{
int i = ;
while (num)
{
map[i--] = num % ;
num /= ;
}
} int Heuristic()
{
int sum = ;
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
{
int k = i * + j;
if (map[k] == ) continue;
sum += abs(i - (map[k] - ) / ) + abs(j - (map[k] - ) % );
}
return sum;
} inline bool inversionNumberCheck()
{
int cnt = ;
for (int i = ; i < ; ++i)
{
if (map[i] == ) continue;
for (int k = i - ; k >= ; --k)
{
if (map[k] == ) continue;
if (map[k] > map[i])
cnt++;
}
}
return cnt & ;
} void FindX(int &x, int &y)
{
for (int i = ; i < ; ++i)
{
if (map[i] == )
{
y = i / ;
x = i % ;
return;
}
}
} int A_star()
{
int state_canto, state_id; state_canto = StateToCanto();
state_id = StateToId();
open[state_canto] += ;
Node start(state_id, , Heuristic(), open[state_canto]);
f[state_canto] = start.f;
find_min.push(start);
pa[state_canto] = -;
dir[state_canto] = ''; if (state_id == )
return state_canto; while (!find_min.empty())
{
Node parent = find_min.top();
Node child;
int p_x, p_y, c_x, c_y, parent_canto;
find_min.pop(); IdToState(parent.id);
parent_canto = StateToCanto();
if (parent.flags != open[parent_canto]) // 一个状态可能被松弛多次,检测parent是否为该状态最后一次松弛的状态
continue;
close[StateToCanto()] = ; // To do FindX(p_x, p_y);
for (int i = ; i < ; ++i)
{
int temp_swap, child_state_conto; c_x = p_x;
c_y = p_y;
c_x += MOVE[i][];
c_y += MOVE[i][]; if (c_x < || c_x >= || c_y < || c_y >= )
continue;
temp_swap = map[p_x + p_y * ];
map[p_x + p_y * ] = map[c_x + c_y * ];
map[c_x + c_y * ] = temp_swap;
child_state_conto = StateToCanto(); if (close[child_state_conto] == )
{
temp_swap = map[p_x + p_y * ];
map[p_x + p_y * ] = map[c_x + c_y * ];
map[c_x + c_y * ] = temp_swap; continue;
} child.id = StateToId();
if (child.id == )
{
pa[child_state_conto] = parent_canto;
dir[child_state_conto] = direction[i];
return child_state_conto;
} child.h = Heuristic();
child.g = parent.g + ;
child.f = child.g + child.h;
child.flags = open[child_state_conto] + ;
pa[child_state_conto] = parent_canto;
dir[child_state_conto] = direction[i];
if (open[child_state_conto] == || f[child_state_conto] > child.f)
{
f[child_state_conto] = child.f;
open[child_state_conto] = child.flags;
find_min.push(child);
}
temp_swap = map[p_x + p_y * ];
map[p_x + p_y * ] = map[c_x + c_y * ];
map[c_x + c_y * ] = temp_swap;
}
}
return -;
} void Find(int i)
{
if (pa[i] == -)
return;
else
{
Find(pa[i]);
printf("%c", dir[i]);
}
} void PrintPath()
{
int end_canto; for (int i = ; i < ; ++i)
map[i] = i + ;
end_canto = StateToCanto(); Find(end_canto);
printf("\n");
} int main()
{
int ans = ; while (scanf("%s", &map[]) != EOF)
{
map[] = (map[] == 'x' ? : (map[] -= ''));
for (int i = ; i < ; ++i)
{
scanf("%s", &map[i]);
map[i] = (map[i] == 'x' ? : (map[i] -= ''));
} if (inversionNumberCheck())
{
printf("unsolvable\n");
continue;
}
memset(open, , sizeof(open));
memset(close, , sizeof(close));
memset(pa, , sizeof(pa));
memset(f, , sizeof(f));
memset(dir, , sizeof(dir));
ans = A_star();
if (ans == -)
printf("unsolvable\n");
else
PrintPath(); while (find_min.empty())
find_min.pop();
}
return ;
}
HDOJ 1043 Eight(A* 搜索)的更多相关文章
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...
- hdu 1043(经典搜索)
题意: 给你一个初始的图,然后每次输入一个图,要求移动x最小的步数达到和初始图一样,输出路径 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 ...
- HDOJ(HDU).1016 Prime Ring Problem (DFS)
HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架 ...
- [dp]HDOJ4960 Another OCD Patient
题意: 给一个n, 第二行给n堆的价值v[i], 第三行给a[i]. a[i]表示把i堆合在一起需要的花费. 求把n堆变成类似回文的 需要的最小花费. 思路: ①记忆化搜索 比较好理解... dp[ ...
- AC Again hdoj 1582 搜索
AC Again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- HDU 1043 八数码(A*搜索)
在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...
- 【HDOJ】1043 Eight
这道题目最开始做的时候wa+TLE.后面知道需要状态压缩,最近A掉.并且练习一下各种搜索算法. 1. 逆向BFS+康拓展开. #include <iostream> #include &l ...
- HDOJ/HDU 2717 Catch That Cow 一维广度优先搜索 so easy..............
看题:http://acm.hdu.edu.cn/showproblem.php?pid=2717 思路:相当于每次有三个方向,加1,减1,乘2,要注意边界条件,减1不能小于0,乘2不能超过最大值. ...
- (中等) HDU 1043 Eight,经典搜索问题。
Problem Description The 15-puzzle has been around for over 100 years; even if you don't know it by t ...
随机推荐
- 在Windows7防火墙允许指定的端口
在xp系统的时代,修改防火墙很方便,很简单.windows7或许是做得过于复杂了.当然所谓安全性也是相当于其他之前版本的系统更高了.为什么要打开端口,肯定是在windows7下启动了网络服务,需要开启 ...
- IO库 8.5
题目:重写8.4中的函数,将每一个单词作为一个独立的元素进行存储. #include <iostream> #include <fstream> #include <st ...
- 在zendstudio上配置SVN
本文介绍zendstudio结合SVN的使用方法. 一.部署svn服务器 直接安装用svn软件,配置太过麻烦,用户和版本库.权限管理不太方便.推荐使用CollabNetSubversionEdge.以 ...
- CSS截取字符串
/*溢出的字...处理*/ .updatecsssubstring { text-overflow: ellipsis; -o-text-overflow: ellipsis; white-space ...
- linux杂记(八)linux压缩与打包
linux系统常见的压缩指令 一般被压缩过的档案,通常其附档名都是[*.tar,*.tar.gz,*.tgz,*.gz,*.Z,*.bz2]等等. *.tar:tar程序打包的数据.并没有压缩过 *. ...
- javaTemplates-学习笔记一
第一步,下载Java运行环境-JDK JDK -'1.8.0_25'[附链接地址] 安装JDK配置环境 安装好jdk,然后配置环境变量.不同系统配置环境变量百度Google之,附上WIN8配置方法[J ...
- Unity 4.2.0 官方最新破解版(Unity3D 最新破解版,3D游戏开发工具和游戏引擎套件)
Unity是一款跨平台的游戏开发工具,从一开始就被设计成易于使用的产品.作为一个完全集成的专业级应用,Unity还包含了价值数百万美元的功能强大的游戏引擎.Unity作为一个游戏开发工具,它的设计主旨 ...
- egret命令行编译项目时 版本不对应的问题
egret 命令行编译项目时 如使用 egret build -e 会出现版本不对应的问题 分析原因 A,B项目 A项目使用1.8的egret引擎, B项目使用2.5引擎 但本地引擎升级至2.5.5, ...
- 关于微信浏览不能URL传参,URL中的问号被删除
关于微信浏览不能URL传参,URL中的问号被删除. 尼玛难道没有人遇到过这个问题?看了微信支付SDK3.0的代码,看到urlencode 看到了几次.实际上 在微信浏览器下 header('locat ...
- poj 3740 Easy Finding 精确匹配
题目链接 dlx的第一题, 真是坎坷..... #include <iostream> #include <vector> #include <cstdio> #i ...