题目链接
http://poj.org/problem?id=1077
分析
直接用BFS进行状态扩展会超时,需要设计估价函数跑A*算法。
每次只能使一个数位置改变,因此未来的操作次数不会小于每个数当前位置于最终位置的曼哈顿距离之和。
用这个作为估价函数,用康托展开将排列映射成整数来记录某一状态是否访问过。
有一结论,如果列数为奇数,那么初始状态和最终状态的逆序对数奇偶性相同。
AC代码
// 调用abs()函数,写上cstdlib, cmath以及using namespace std
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
const int maxn = 15, maxs = 362885;
const int nxt[4][2] = {
{
-1, 0}, {
1, 0}, {
0, -1}, {
0, 1}};
const char dir[4] = {
'u', 'd', 'l', 'r'};
int bit[maxn], fact[maxn];
inline int ask(int x) {
int ret = 0;
while (x) ret += bit[x], x -= x & -x;
return ret;
}
inline void add(int x, int d