From 2739bd39a40434dbe06deef243f4b8539b4fae26 Mon Sep 17 00:00:00 2001 From: Tifa <62847935+Tiphereth-A@users.noreply.github.com> Date: Thu, 8 Feb 2024 05:26:37 +0800 Subject: [PATCH] fix: tiny change --- src/code/game/npuzzle_data.hpp | 89 ++++++++++--------- src/code/tree/height.hpp | 10 +-- src/src/npuzzle_data_usage.txt | 12 ++- src/test_cpverifier/aizu/alds1_13_b.test.cpp | 18 ++++ src/test_cpverifier/aizu/alds1_13_c.test.cpp | 11 ++- .../hackerrank/n-puzzle.test.cpp | 22 ----- 6 files changed, 85 insertions(+), 77 deletions(-) create mode 100644 src/test_cpverifier/aizu/alds1_13_b.test.cpp delete mode 100644 src/test_cpverifier/hackerrank/n-puzzle.test.cpp diff --git a/src/code/game/npuzzle_data.hpp b/src/code/game/npuzzle_data.hpp index 7c93f2679..0ea264da0 100644 --- a/src/code/game/npuzzle_data.hpp +++ b/src/code/game/npuzzle_data.hpp @@ -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 fin_node; + static inline vvec pos_cost; + u32 k, pos0; - vec node_; - vec 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 const &fin) { + assert(fin.size() == k * k); + fin_node = fin; + pos_cost.resize(k * k, vec(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 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 next() { auto moves = gen_move(); - vec ans(moves.size(), *this); - for (u32 i = 0; i < moves.size(); ++i) ans[i].move(moves[i]); + vec 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 gen_move() const { - vec 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()); } }; diff --git a/src/code/tree/height.hpp b/src/code/tree/height.hpp index 0c44d645e..bcd36cb87 100644 --- a/src/code/tree/height.hpp +++ b/src/code/tree/height.hpp @@ -7,9 +7,8 @@ namespace tifa_libs::graph { template constexpr auto tree_height(G const &tr) { - u32 n = (u32)tr.g.size(); using T = typename G::weight_type; - vec h(n); + u32 n = (u32)tr.g.size(); vvec _(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 { @@ -17,13 +16,14 @@ constexpr auto tree_height(G const &tr) { auto &&es = tr.g[u]; for (u32 i = 0; i < es.size(); ++i) if constexpr (std::is_base_of_v) { - 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 h(n); + for (u32 i = 0; i < n; ++i) h[i] = f(f, i, i); return h; } diff --git a/src/src/npuzzle_data_usage.txt b/src/src/npuzzle_data_usage.txt index f432923b8..77939b450 100644 --- a/src/src/npuzzle_data_usage.txt +++ b/src/src/npuzzle_data_usage.txt @@ -1,9 +1,15 @@ int k = 4; // 15-puzzle - NPuzzleData start(k); + +// 初始化终止局面 +std::vector 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; diff --git a/src/test_cpverifier/aizu/alds1_13_b.test.cpp b/src/test_cpverifier/aizu/alds1_13_b.test.cpp new file mode 100644 index 000000000..55ad81a69 --- /dev/null +++ b/src/test_cpverifier/aizu/alds1_13_b.test.cpp @@ -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 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; +} diff --git a/src/test_cpverifier/aizu/alds1_13_c.test.cpp b/src/test_cpverifier/aizu/alds1_13_c.test.cpp index 0d715d626..40ef03855 100644 --- a/src/test_cpverifier/aizu/alds1_13_c.test.cpp +++ b/src/test_cpverifier/aizu/alds1_13_c.test.cpp @@ -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" @@ -7,10 +8,12 @@ int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); tifa_libs::game::NPuzzleData start(4); + std::vector 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; } diff --git a/src/test_cpverifier/hackerrank/n-puzzle.test.cpp b/src/test_cpverifier/hackerrank/n-puzzle.test.cpp deleted file mode 100644 index 2cf71cb23..000000000 --- a/src/test_cpverifier/hackerrank/n-puzzle.test.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#define PROBLEM "https://www.hackerrank.com/challenges/n-puzzle/problem" - -#include "../../code/game/npuzzle_data.hpp" -#include "../../code/opt/astar.hpp" - -int main() { - std::ios::sync_with_stdio(false); - std::cin.tie(nullptr); - u32 n; - std::cin >> n; - tifa_libs::game::NPuzzleData start(n); - std::cin >> start; - auto v = tifa_libs::opt::astar(start)->moves(); - std::cout << v.size() << '\n'; - for (auto i : v) switch (i) { - case tifa_libs::game::U: std::cout << "UP\n"; break; - case tifa_libs::game::D: std::cout << "DOWN\n"; break; - case tifa_libs::game::L: std::cout << "LEFT\n"; break; - case tifa_libs::game::R: std::cout << "RIGHT\n"; break; - } - return 0; -}