Skip to content

Commit

Permalink
fix: tiny change
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiphereth-A committed Feb 8, 2024
1 parent b1e33d7 commit 2739bd3
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 77 deletions.
89 changes: 46 additions & 43 deletions src/code/game/npuzzle_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,74 +6,77 @@

namespace tifa_libs::game {

// clang-format off
enum Dir4 { U, D, L, R };
// clang-format on

// n = k*k-1
class NPuzzleData {
static inline vec<u32> fin_node;
static inline vvec<u32> pos_cost;

u32 k, pos0;
vec<u32> node_;
vec<Dir4> moves_;
u32 cost_;

public:
constexpr explicit NPuzzleData(u32 k) : k(k) {}
static inline u32 limit = UINT32_MAX;
static constexpr void set_fin(u32 k, vec<u32> const &fin) {
assert(fin.size() == k * k);
fin_node = fin;
pos_cost.resize(k * k, vec<u32>(k * k));
for (u32 p = 0; p < k * k; ++p)
for (u32 q = 0; q < k * k; ++q) pos_cost[p][q] = u32(abs(i32(p / k) - i32(q / k)) + abs(i32(p % k) - i32(q % k)));
}

constexpr auto const &cost() const { return cost_; }
constexpr auto &node() { return node_; }
constexpr auto const &node() const { return node_; }
constexpr auto const &moves() const { return moves_; }
vec<u32> node;
strn moves;
constexpr explicit NPuzzleData(u32 k) : k(k) { node.resize(k * k); }

constexpr bool solved() {
for (u32 i = 0; i < node_.size(); ++i)
if (node_[i] != i) return 0;
return 1;
}
constexpr auto const &cost() const { return cost_; }
constexpr bool solved() { return node == fin_node; }
constexpr vec<NPuzzleData> next() {
auto moves = gen_move();
vec<NPuzzleData> ans(moves.size(), *this);
for (u32 i = 0; i < moves.size(); ++i) ans[i].move(moves[i]);
vec<NPuzzleData> ans;
for (char d : moves) {
auto nxt = *this;
nxt.move(d);
if (nxt.cost_ <= limit) ans.push_back(nxt);
}
return ans;
}
constexpr void move(Dir4 dir) {
moves_.push_back(dir);
constexpr void move(char dir) {
moves.push_back(dir);
++cost_;
u32 _ = pos0;
switch (dir) {
case U: pos0 -= k; break;
case D: pos0 += k; break;
case L: --pos0; break;
case R: ++pos0; break;
case 'U': pos0 -= k; break;
case 'D': pos0 += k; break;
case 'L': --pos0; break;
case 'R': ++pos0; break;
}
std::swap(node_[_], node_[pos0]);
cost_ = gen_cost();
cost_ += pos_cost[node[pos0]][fin_node[_]];
cost_ -= pos_cost[node[pos0]][fin_node[pos0]];
std::swap(node[_], node[pos0]);
}

constexpr auto operator<=>(NPuzzleData const &node) const { return node_ <=> node.node_; }

constexpr auto operator<=>(NPuzzleData const &r) const { return node <=> r.node; }
friend std::istream &operator>>(std::istream &is, NPuzzleData &np) {
np.node_.resize(np.k * np.k);
for (auto &i : np.node_) is >> i;
np.pos0 = u32(std::find(np.node_.begin(), np.node_.end(), 0) - np.node_.begin());
for (auto &i : np.node) is >> i;
np.pos0 = u32(std::find(np.node.begin(), np.node.end(), 0) - np.node.begin());
np.cost_ = np.gen_cost();
return is;
}

private:
constexpr vec<Dir4> gen_move() const {
vec<Dir4> ans;
if (pos0 / k) ans.push_back(U);
if (pos0 / k != k - 1) ans.push_back(D);
if (pos0 % k) ans.push_back(L);
if (pos0 % k != k - 1) ans.push_back(R);
constexpr strn gen_move() const {
strn ans;
char lst = moves.back();
if (pos0 / k && lst != 'D') ans += 'U';
if (pos0 / k != k - 1 && lst != 'U') ans += 'D';
if (pos0 % k && lst != 'R') ans += 'L';
if (pos0 % k != k - 1 && lst != 'L') ans += 'R';
return ans;
}
constexpr u32 gen_cost() const {
u32 h1 = 0, h2 = 0;
for (u32 i = 0; i < k; ++i)
for (u32 j = 0; j < k; ++j)
if (u32 _ = node_[k * i + j]; _ != k * i + j && _) ++h1, h2 += u32(abs((i32)i - i32(_ / k)) + abs((i32)j - i32(_ % k)));
return std::max(h1, h2) + (u32)moves_.size();
u32 h = 0;
for (u32 p = 0; p < k * k; ++p)
if (node[p] != fin_node[p] && node[p]) h += pos_cost[node[p]][fin_node[p]];
return u32(h + moves.size());
}
};

Expand Down
10 changes: 5 additions & 5 deletions src/code/tree/height.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@ namespace tifa_libs::graph {

template <class G>
constexpr auto tree_height(G const &tr) {
u32 n = (u32)tr.g.size();
using T = typename G::weight_type;
vec<T> h(n);
u32 n = (u32)tr.g.size();
vvec<T> _(n);
for (u32 i = 0; i < n; ++i) _[i].resize(tr.g[i].size(), T(-1));
auto f = [&](auto &&f, u32 u, u32 fa) -> T {
T ans = 0;
auto &&es = tr.g[u];
for (u32 i = 0; i < es.size(); ++i)
if constexpr (std::is_base_of_v<alist, G>) {
if (auto &&v = es[i]; v != fa) ans = std::max(ans, (_[u][i] = _[u][i] == T(-1) ? f(f, v, u) : _[u][i]) + 1);
if (auto &&v = es[i]; v != fa) ans = std::max(ans, (_[u][i] = (_[u][i] == T(-1) ? f(f, v, u) : _[u][i])) + 1);
} else {
if (auto &&[v, w] = es[i]; v != fa) ans = std::max(ans, (_[u][i] = _[u][i] == T(-1) ? f(f, v, u) : _[u][i]) + w);
if (auto &&[v, w] = es[i]; v != fa) ans = std::max(ans, (_[u][i] = (_[u][i] == T(-1) ? f(f, v, u) : _[u][i])) + w);
}
return ans;
};
for (u32 i = 0; i < n; ++i) h[i] = f(f, i, 0);
vec<T> h(n);
for (u32 i = 0; i < n; ++i) h[i] = f(f, i, i);
return h;
}

Expand Down
12 changes: 9 additions & 3 deletions src/src/npuzzle_data_usage.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
int k = 4; // 15-puzzle

NPuzzleData start(k);

// 初始化终止局面
std::vector<u32> fin(k * k);
std::iota(fin.begin(), fin.end(), 0);
NPuzzleData::set_fin(k, fin);
// 初始化最大估价
tifa_libs::game::NPuzzleData::limit = 100;
// 读入局面
std::cin >> start;
// 输出当前局面
std::cout << start.node();
std::cout << start.node;
// 输出操作步骤
std::cout << astar(start)->moves();
std::cout << astar(start)->moves;
18 changes: 18 additions & 0 deletions src/test_cpverifier/aizu/alds1_13_b.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/all/ALDS1_13_B"

#include "../../code/game/npuzzle_data.hpp"
#include "../../code/opt/astar.hpp"

int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
tifa_libs::game::NPuzzleData start(3);
std::vector<u32> fin(9);
std::iota(fin.begin(), fin.end(), 1);
fin.back() = 0;
tifa_libs::game::NPuzzleData::set_fin(3, fin);
tifa_libs::game::NPuzzleData::limit = 100;
std::cin >> start;
std::cout << tifa_libs::opt::astar(start)->moves.size() << '\n';
return 0;
}
11 changes: 7 additions & 4 deletions src/test_cpverifier/aizu/alds1_13_c.test.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/all/ALDS1_13_C"
#define TLE 10

#include "../../code/game/npuzzle_data.hpp"
#include "../../code/opt/astar.hpp"
Expand All @@ -7,10 +8,12 @@ int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
tifa_libs::game::NPuzzleData start(4);
std::vector<u32> fin(16);
std::iota(fin.begin(), fin.end(), 1);
fin.back() = 0;
tifa_libs::game::NPuzzleData::set_fin(4, fin);
tifa_libs::game::NPuzzleData::limit = 100;
std::cin >> start;
for (auto& i : start.node())
if (i) --i;
else i = 15;
std::cout << tifa_libs::opt::astar(start)->moves().size() << '\n';
std::cout << tifa_libs::opt::astar(start)->moves.size() << '\n';
return 0;
}
22 changes: 0 additions & 22 deletions src/test_cpverifier/hackerrank/n-puzzle.test.cpp

This file was deleted.

0 comments on commit 2739bd3

Please sign in to comment.