119 lines
2.1 KiB
C++
119 lines
2.1 KiB
C++
/*
|
|
compilation command:
|
|
g++ -O3 -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` astar.cpp -o astar`python3-config --extension-suffix`
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <queue>
|
|
#include <unordered_map>
|
|
|
|
#include <pybind11/pybind11.h>
|
|
#include <pybind11/stl.h>
|
|
|
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
|
|
|
namespace py = pybind11;
|
|
|
|
using namespace std;
|
|
|
|
int deltas[4] = {-16, 16, -1, 1};
|
|
|
|
struct result
|
|
{
|
|
double cost;
|
|
int players;
|
|
};
|
|
|
|
struct result cost(const vector<double> &t, int players, int exits, int m, int l)
|
|
{
|
|
int i, n, dn, p, e, mask;
|
|
double c, v;
|
|
struct result r;
|
|
p = players;
|
|
dn = deltas[m];
|
|
c = 1;
|
|
for(i = 0; i < 4; ++i)
|
|
{
|
|
n = p >> i * 8 & 0xff;
|
|
e = exits >> i * 8 & 0xff;
|
|
if(n == e) continue;
|
|
n += dn;
|
|
v = t[n + i * l];
|
|
if(v < 0) continue;
|
|
mask = 0xff << i * 8;
|
|
p = (p & ~mask) | (n << i * 8);
|
|
c += v;
|
|
}
|
|
r.cost = c;
|
|
r.players = p;
|
|
return r;
|
|
}
|
|
|
|
double heuristic(int u, int d)
|
|
{
|
|
int result, dx[4], i;
|
|
for(i = 0; i < 4; ++i)
|
|
{
|
|
dx[i] = abs(u >> i * 8 & 0xff) % 16 - abs(d >> i * 8 & 0xff) % 16 ;
|
|
}
|
|
return MAX(dx[0], dx[2]) + MAX(dx[1], dx[3]);
|
|
}
|
|
|
|
vector<int> astar(const vector<double> &t, int s, int d, int l)
|
|
{
|
|
int m, n, u;
|
|
double c, cu;
|
|
struct result r;
|
|
vector<int> path;
|
|
typedef pair<double, int> element;
|
|
priority_queue<element, vector<element>, greater<element> > q;
|
|
unordered_map<int, int> prev, move;
|
|
unordered_map<int, double> dist;
|
|
|
|
q.emplace(0, s);
|
|
prev[s] = s;
|
|
dist[s] = 0;
|
|
move[s] = 0;
|
|
|
|
while(!q.empty())
|
|
{
|
|
u = q.top().second;
|
|
q.pop();
|
|
if(u == d) break;
|
|
cu = dist[u];
|
|
for(m = 0; m < 4; ++m)
|
|
{
|
|
r = cost(t, u, d, m, l);
|
|
c = r.cost;
|
|
n = r.players;
|
|
if(u == n) continue;
|
|
c += cu;
|
|
if(dist.find(n) == dist.end() || c < dist[n])
|
|
{
|
|
q.emplace(c + heuristic(n, d), n);
|
|
prev[n] = u;
|
|
dist[n] = c;
|
|
move[n] = m;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(u == d)
|
|
{
|
|
while(u != s)
|
|
{
|
|
path.push_back(move[u]);
|
|
u = prev[u];
|
|
}
|
|
reverse(path.begin(), path.end());
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
PYBIND11_MODULE(astar, m)
|
|
{
|
|
m.def("astar", &astar, "");
|
|
}
|