题目链接: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. Java随机数生成原理--转稿

    1.Math库里的static(静态)方法random() 该方法的作用是产生0到1之间(包括0,但不包括1)的一个double值. double rand = Math.random(); 2.通过 ...

  2. Hive常用操作之数据导入导出

    一.Hive数据导入导出 1.hive数据导出 很多时候,我们在hive中执行select语句,希望将最终的结果保存到本地文件或者保存到hdfs系统中或者保存到一个新的表中,hive提供了方便的关键词 ...

  3. 百度apistore第三方登陆

    最近做一个个人博客,其中的登陆模块我想使用第三方登陆来做.上网搜一下有好多例子,但是大多数都是一个网站的第三方登陆,如QQ.微博.人人,没有集成的组件,于是就在网上搜一下百度的apistore,百度果 ...

  4. JQuery中serialize() 序列化

    更多2014/8/24 来源:jquery学习浏览量:1671 学习标签: serialize 本文导读:在jQuery中,当我们使用ajax时,常常需要拼装input数据以键值对(Key/Value ...

  5. nodejs事件机制

    var EventEmitter = function() { this.evts = {}; }; EventEmitter.prototype = { constructor: EventEmit ...

  6. Python数据分析扩展库

    Anaconda和Python(x,y)都自带了下面的这些库. 1. NumPy 强大的ndarray和ufunc函数. import numpy as np xArray = np.ones((3, ...

  7. NET CORE 应用程序启动

    原文:Application Startup作者:Steve Smith翻译:刘怡(AlexLEWIS)校对:谢炀(kiler398).许登洋(Seay) ASP.NET Core 为你的应用程序提供 ...

  8. html5 note

    HTML5的特点 绘图支持 canvas 多媒体支持 video audio 离线应用 和 离线存储 新的语义化元素 article footer header nav section 表单增强 ca ...

  9. Android SharedPreference最佳实践

    Android提供多种方式保存应用数据,其中一种方式是SharedPreferences,使用键值对保存私有基本的数据.所有的逻辑仅基于以下三个类: SharedPreferences SharedP ...

  10. OpenStack安装部署管理中常见问题解决方法

    一.网络问题-network 更多网络原理机制可以参考<OpenStack云平台的网络模式及其工作机制>. 1.1.控制节点与网络控制器区别 OpenStack平台中有两种类型的物理节点, ...