mirror of https://github.com/dnomd343/klotski.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
3.0 KiB
74 lines
3.0 KiB
#include <algorithm>
|
|
#include "analyse.h"
|
|
|
|
Analyse::track_data_t Analyse::backtrack(const std::vector<RawCode> &codes) {
|
|
/// codes pre-check and sort by steps
|
|
std::vector<std::vector<analyse_t*>> todos;
|
|
for (const auto &code : codes) {
|
|
auto c = cases.find((uint64_t)code);
|
|
if (c == cases.end()) { // invalid input
|
|
return track_data_t{}; // return empty data
|
|
}
|
|
if (c->second.step >= todos.size()) {
|
|
todos.resize(c->second.step + 1); // enlarge schedule list
|
|
}
|
|
todos[c->second.step].emplace_back(&c->second);
|
|
}
|
|
std::reverse(todos.begin(), todos.end()); // backtrack start from further layer
|
|
|
|
struct cache_t {
|
|
analyse_t *a;
|
|
track_t *b;
|
|
};
|
|
std::queue<cache_t> track_cache;
|
|
track_data_t track_data(todos.size());
|
|
/// start backtrack process
|
|
for (const auto &todo : todos) {
|
|
if (todo.empty()) {
|
|
continue; // without scheduled cases
|
|
}
|
|
std::queue<cache_t>{}.swap(track_cache); // clear track cache
|
|
for (const auto c : todo) {
|
|
/// case already exist -> skip its backtrack
|
|
if (track_data[c->step].find(c->code) == track_data[c->step].end()) {
|
|
track_cache.emplace(cache_t{
|
|
.a = c,
|
|
.b = &track_data[c->step].emplace(c->code, track_t{
|
|
.code = c->code,
|
|
.layer_num = c->step,
|
|
.last = std::list<track_t*>{}, // without parent node
|
|
.next = std::list<track_t*>{}, // without sub node
|
|
}).first->second,
|
|
});
|
|
}
|
|
}
|
|
/// backtrack until root case
|
|
while (!track_cache.empty()) {
|
|
auto curr = track_cache.front(); // handle first element
|
|
for (auto src : curr.a->src) { // traverse src cases of current node
|
|
auto t_src = track_data[src->step].find(src->code);
|
|
if (t_src != track_data[src->step].end()) { // match src case
|
|
/// link (curr.b) and (t_src->second)
|
|
t_src->second.next.emplace_back(curr.b);
|
|
curr.b->last.emplace_back(&t_src->second);
|
|
} else { // src case not found
|
|
/// link (curr.b) and (t_src_new->second)
|
|
auto t_src_new = track_data[src->step].emplace(src->code, track_t {
|
|
.code = src->code,
|
|
.layer_num = src->step,
|
|
.last = std::list<track_t*>{},
|
|
.next = std::list<track_t*>{curr.b}, // link to curr.b
|
|
}).first;
|
|
curr.b->last.emplace_back(&t_src_new->second);
|
|
/// insert into working queue
|
|
track_cache.emplace(cache_t {
|
|
.a = src,
|
|
.b = &t_src_new->second,
|
|
});
|
|
}
|
|
}
|
|
track_cache.pop();
|
|
}
|
|
}
|
|
return track_data;
|
|
}
|
|
|