题目链接: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* 搜索)的更多相关文章

  1. BFS(八数码) POJ 1077 || HDOJ 1043 Eight

    题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...

  2. 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 ...

  3. HDOJ(HDU).1016 Prime Ring Problem (DFS)

    HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架 ...

  4. [dp]HDOJ4960 Another OCD Patient

    题意: 给一个n, 第二行给n堆的价值v[i], 第三行给a[i].  a[i]表示把i堆合在一起需要的花费. 求把n堆变成类似回文的 需要的最小花费. 思路: ①记忆化搜索 比较好理解... dp[ ...

  5. AC Again hdoj 1582 搜索

    AC Again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  6. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  7. 【HDOJ】1043 Eight

    这道题目最开始做的时候wa+TLE.后面知道需要状态压缩,最近A掉.并且练习一下各种搜索算法. 1. 逆向BFS+康拓展开. #include <iostream> #include &l ...

  8. HDOJ/HDU 2717 Catch That Cow 一维广度优先搜索 so easy..............

    看题:http://acm.hdu.edu.cn/showproblem.php?pid=2717 思路:相当于每次有三个方向,加1,减1,乘2,要注意边界条件,减1不能小于0,乘2不能超过最大值. ...

  9. (中等) HDU 1043 Eight,经典搜索问题。

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

随机推荐

  1. (4)事件处理——(1)事件处理(Handling Events)

    JavaScript has several built-in ways of reacting to user interaction and other events. To make a pag ...

  2. 修改IIS虚拟目录名称

    @echo off echo ------------------------------------------------------------------------------ echo - ...

  3. 转:angular的decorator方法

    AngularJS实例 – 装饰$log 在AngularJS中,我们可以使用Angular内置或者自定义的services,在应用的各个部分之间分享数据和方法.假设你已经定义了一个service,但 ...

  4. PE头的应用---插入代码到EXE或DLL文件中

    三.代码实现(DELPHI版本),采用第三种方式实现代码插入. 1. 定义两个类,一个用来实现在内存中建立输入表:一个用来实现对PE头的代码插入. DelphiCode: const MAX_SECT ...

  5. 淘宝数据库连接池 druid 性能评测

    想必大家知道淘宝在双十一惊人表现,搜索群里有哥们对淘宝的链接池进行了测试,废话不多说,直接上测试结果,结果如下:在Spring中使用方法<bean id="dataSource&quo ...

  6. Jsoup代码解读之五-实现一个CSS Selector

    Jsoup代码解读之七-实现一个CSS Selector 当当当!终于来到了Jsoup的特色:CSS Selector部分.selector也是我写的爬虫框架webmagic开发的一个重点.附上一张s ...

  7. Codeforces Round #242 (Div. 2) &lt;A-D&gt;

    CF424 A. Squats 题目意思: 有n(n为偶数)个x和X,求最少的变换次数,使得X的个数为n/2,输出变换后的序列. 解题思路: 统计X的个数ans,和n/2比較,少了的话,须要把n/2- ...

  8. 理解Android的layout和measure

    在Android UI开发中,总会有情况需要自定义View和View Group. 什么是View?就是Android中一个基本视图单位,一个Button是一个view, 一个Layout, 也是一个 ...

  9. ubuntu之iptables

    1.更新iptables并立即生效: a.保存当前设置:iptables-save > /etc/iptables.up.rules b.修改iptables规则: 例如: -I INPUT - ...

  10. os基础

    命令:指计算机用户要求计算机系统为其工作的指示: 命令的表示形式: 1.字符形式: 2.菜单形式: 3.图形形式: 命令的使用方式:1. 脱机使用方式 off_line       2.联机使用方式  ...