题目链接: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. Hibernate中为什么要重写equals方法和hashcode方法

    1.*为什么要重写equals方法,首先我们来看一下equals源码: public boolean equals(Object anObject) { if (this == anObject) { ...

  2. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  3. html字符实体对照表

  4. nyoj 21三个水杯(BFS + 栈)

    题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=21 思想: 看了一下搜索就来写了这题(BFS 找出最短路径 所以用此来进行搜索) 这题在 ...

  5. Radio Checkbox Select 操作

    一个小总结 <!DOCTYPE html> <html> <head> <meta name="description" content= ...

  6. ElasticSearch D3

    http://www.elasticsearch.org/blog/data-visualization-elasticsearch-aggregations/

  7. HDU 3501 Calculation 2

    题目大意:求小于n的与n不互质的数的和. 题解:首先欧拉函数可以求出小于n的与n互质的数的个数,然后我们可以发现这样一个性质,当x与n互质时,n-x与n互质,那么所有小于n与n互质的数总是可以两两配对 ...

  8. jquery 使用ajax调用c#后台方法

    $.ajax({                         type: "get",                         cache: false,        ...

  9. Android Fragment 嵌套使用报错

    在新的SDK每次创建activity时,会自己主动生成  <pre name="code" class="java">public static c ...

  10. Head First设计模式学习笔记

    最近在学C++,直接语法之后觉得不太有意思,直接做项目又觉得太肤浅.正好之前一直想学设计模式来着,可惜之前一直在玩C,所以没有机会深入学习,于是决定用C++把设计写一遍.看了点GOF的<设计模式 ...