結果
問題 | No.5019 Hakai Project |
ユーザー |
![]() |
提出日時 | 2023-11-18 18:55:40 |
言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,953 ms / 3,000 ms |
コード長 | 53,855 bytes |
コンパイル時間 | 6,143 ms |
コンパイル使用メモリ | 304,152 KB |
実行使用メモリ | 354,880 KB |
スコア | 2,434,147,186 |
最終ジャッジ日時 | 2023-11-18 18:58:22 |
合計ジャッジ時間 | 160,695 ms |
ジャッジサーバーID (参考情報) |
judge11 / judge15 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
コンパイルメッセージ
main.cpp:409:22: warning: class 'CapArr<T, CAP>' is implicitly friends with itself 409 | friend class CapArr; | ^~~~~~
ソースコード
#define CODETEST 0#define OPTUNE 0#define PERFORMANCE 0#define EVAL 0#define UNIT_TEST 0#define TIME_LIMIT (2800)#define NOT_SUBMIT 0#define VALIDATION 0#define IO_FILE 0#define OUTPUT_INFO 0#define OUTPUT_FINAL_INFO 0#define OUTPUT_LOG 0#define OUTPUT_VISUAL 0#define FIX_RESULT 0#define TIME_LIMIT_US (TIME_LIMIT * 1000)#ifdef __clang_version__#pragma clang diagnostic ignored "-Wunknown-pragmas"#pragma clang diagnostic ignored "-Wunknown-warning-option"#pragma clang diagnostic ignored "-Wmissing-braces"#endif#ifndef _MSC_VER#pragma GCC target ("avx2")#pragma GCC optimize "O3,omit-frame-pointer,inline"#pragma GCC optimize ("unroll-loops")#pragma GCC diagnostic ignored "-Wunused-parameter"#pragma GCC diagnostic ignored "-Wsign-compare"#pragma GCC diagnostic ignored "-Wunused-variable"#pragma GCC diagnostic ignored "-Wunused-function"#pragma GCC diagnostic ignored "-Wunused-but-set-variable"#endif#define _USE_MATH_DEFINES#ifdef __clang_version__#include <cassert>#include <cctype>#include <cerrno>#include <cfloat>#include <ciso646>#include <climits>#include <clocale>#include <cmath>#include <csetjmp>#include <csignal>#include <cstdarg>#include <cstddef>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <cfenv>#include <cinttypes>#include <cstdint>#include <cwchar>#include <cwctype>#include <algorithm>#include <bitset>#include <complex>#include <deque>#include <exception>#include <fstream>#include <functional>#include <iomanip>#include <ios>#include <iosfwd>#include <iostream>#include <istream>#include <iterator>#include <limits>#include <list>#include <locale>#include <map>#include <memory>#include <new>#include <numeric>#include <ostream>#include <queue>#include <set>#include <sstream>#include <stack>#include <stdexcept>#include <streambuf>#include <string>#include <typeinfo>#include <utility>#include <valarray>#include <vector>#include <array>#include <atomic>#include <chrono>#include <condition_variable>#include <forward_list>#include <future>#include <initializer_list>#include <mutex>#include <random>#include <ratio>#include <regex>#include <system_error>#include <thread>#include <tuple>#include <typeindex>#include <type_traits>#include <unordered_map>#include <unordered_set>#else#include <bits/stdc++.h>#endifusing namespace std;#define FOR(i, s, e) for (int i = int(s); i < int(e); ++i)#define RFOR(i, s, e) for (int i = int(e) - 1; i >= int(s); --i)#define REP(i, n) for (int i = 0, i##_size = int(n); i < i##_size; ++i)#define RREP(i, n) for (int i = int(n) - 1; i >= 0; --i)#define ALL(x) (x).begin(),(x).end()template <class T, class U> inline void chmin(T& a, U&& b) { if (b < a) { a = b; } }template <class T, class U> inline void chmax(T& a, U&& b) { if (a < b) { a = b; } }template <class T, class U, class V> inline void clip(T& v, U&& lower, V&& upper) {if (v < lower) { v = lower; }else if (v > upper) { v = upper; }}template <class T> inline constexpr T square(T v) { return v * v; }template <class T, int SIZE>constexpr int len(const T(&)[SIZE]) { return SIZE; }#define cauto const auto#include <cstdint>using u8 = uint8_t;using u16 = uint16_t;using u32 = uint32_t;using u64 = uint64_t;using s8 = int8_t;using s16 = int16_t;using s32 = int32_t;using s64 = int64_t;using TimePoint = chrono::high_resolution_clock::time_point;struct ChronoTimer {private:TimePoint startTime_;TimePoint endTime_;public:inline void Init() {startTime_ = chrono::high_resolution_clock::now();endTime_ = startTime_;}inline void Start(int limit) {endTime_ = startTime_ + chrono::milliseconds(limit);}inline void StartMs(int limit) {endTime_ = startTime_ + chrono::milliseconds(limit);}inline void StartUs(int limit) {endTime_ = startTime_ + chrono::microseconds(limit);}inline void Join() {}inline bool IsOver() const {return chrono::high_resolution_clock::now() >= endTime_;}inline int ElapseTimeMs() const {return (int)chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - startTime_).count();}inline int ElapseTimeUs() const {return (int)chrono::duration_cast<chrono::microseconds>(chrono::high_resolution_clock::now() - startTime_).count();}void SetElapseTimeMs(int ms) {auto now = chrono::high_resolution_clock::now();auto limit = endTime_ - startTime_;startTime_ = now - chrono::milliseconds(ms);endTime_ = startTime_ + limit;}inline int LeftToUS(const TimePoint& limit) const {return (int)chrono::duration_cast<chrono::microseconds>(limit - chrono::high_resolution_clock::now()).count();}inline double NowRate() const {return (chrono::high_resolution_clock::now() - startTime_).count() / (double)(endTime_ - startTime_).count();}inline TimePoint Now() const {return chrono::high_resolution_clock::now();}inline TimePoint StartTime() const {return startTime_;}inline TimePoint EndTime() const {return endTime_;}TimePoint GetLimitTimePointUs(int limit) const {return startTime_ + chrono::microseconds(limit);}};TimePoint Now() {return chrono::high_resolution_clock::now();}template <class T>void InstanceRun(int argc, const char* argv[]) {T* m = new T;m->Run(argc, argv);quick_exit(0);}struct Main;signed main(int argc, const char* argv[]) {cin.tie(0);ios::sync_with_stdio(0);InstanceRun<Main>(argc, argv);}struct MemoryException {};#define VALIDATE_ABORT()#define VALIDATE_ASSERT(exp)#define VABORT() VALIDATE_ABORT()#define VASSERT(exp) VALIDATE_ASSERT(exp)template <class A, class B>struct pr {union {A a;A x;A first;};union {B b;B y;B second;};bool operator == (pr const& r) const { return a == r.a && b == r.b; }bool operator != (pr const& r) const { return !((*this) == r); }bool operator < (pr const& r) const {if (a == r.a) {return b < r.b;}return a < r.a;}bool operator > (pr const& r) const {return r < (*this);}pr& operator += (pr const& v) {a += v.a;b += v.b;return *this;}pr& operator -= (pr const& v) {a -= v.a;b -= v.b;return *this;}template <class C, class D>auto operator + (pr<C, D> const& v) const {return pr<decltype(a + v.a), decltype(b + v.b)>{ a + v.a, b + v.b };}template <class C, class D>auto operator - (pr<C, D> const& v) const {return pr<decltype(a - v.a), decltype(b - v.b)>{ a - v.a, b - v.b };}template <class C, class D>explicit operator pr<C, D>() const {return { C(a), D(b) };}template <class T>auto operator * (T const& v) const -> pr<decltype(x * v), decltype(y * v)> {return { x * v, y * v };}template <class T>auto operator / (T const& v) const -> pr<decltype(x / v), decltype(y / v)> {return { x / v, y / v };}template <class T>pr& operator *= (T const& v) {x *= v;y *= v;return *this;}template <class T>pr& operator /= (T const& v) {x /= v;y /= v;return *this;}pr operator -() const {return pr{ -x, -y };}void flip() { swap(x, y); }friend istream& operator>>(istream& is, pr& p) {is >> p.a >> p.b;return is;}friend ostream& operator<<(ostream& os, pr const& p) {os << p.a << " " << p.b;return os;}template <size_t I>auto get() const {if constexpr (I == 0) {return x;}else if constexpr (I == 1) {return y;}}};using pint = pr<int, int>;using pdouble = pr<double, double>;static_assert(is_trivially_copyable<pint>::value, "not trivially_copyable");template <class A, class B>struct tuple_size<pr<A, B>> : integral_constant<size_t, 2> {};template <class A, class B>struct tuple_element<0, pr<A, B>> { using type = A; };template <class A, class B>struct tuple_element<1, pr<A, B>> { using type = B; };inline pdouble ToDouble(const pint& p) {return pdouble{ double(p.x), double(p.y) };}inline pint round(const pdouble& d) {return pint{ (int)round(d.x), (int)round(d.y) };}inline double norm(const pdouble& d) {return sqrt((d.x * d.x) + (d.y * d.y));}inline double norm(const pint& d) {return norm(ToDouble(d));}inline int norm2(const pint& d) {return square(d.x) + square(d.y);}inline pdouble normalized(const pdouble& d) {return d / norm(d);}inline double dot(const pdouble& a, const pdouble& b) {return a.x * b.x + a.y * b.y;}inline double cross(const pdouble& a, const pdouble& b) {return a.x * b.y - a.y * b.x;}template <class T, int CAP>class CapArr {private:friend class CapArr;static_assert(is_trivially_copyable<T>::value);T array_[CAP];int size_ = 0;public:bool operator == (const CapArr<T, CAP>& r) const {if (size_ != r.size_) {return false;}REP(i, size_) {if (!(array_[i] == r.array_[i])) {return false;}}return true;}template <class U, int U_CAP>bool operator != (const CapArr<U, U_CAP>& r) const {return !(*this == r);}bool MemEqual(const CapArr<T, CAP>& r) const {if (size_ != r.size_) {return false;}return memcmp(data(), r.data(), sizeof(T) * size_) == 0;}constexpr int capacity() const {return CAP;}int size() const {return size_;}bool empty() const {return size_ == 0;}void clear() {size_ = 0;}void resize(int size) {size_ = size;}void assign(int size, const T& e) {size_ = size;if constexpr (sizeof(T) == 1) {if constexpr (is_enum<T>::value) {memset(data(), underlying_type<T>::type(e), size);}else {memset(data(), *reinterpret_cast<const unsigned char*>(&e), size);}}else {for (int i = 0; i < size; ++i) {array_[i] = e;}}}void AssignIota(int size) {resize(size);iota(begin(), end(), 0);}void Iota(int size) {resize(size);iota(begin(), end(), 0);}void MemAssign(int size, int byte) {size_ = size;memset(data(), byte, sizeof(T) * size);}void MemCopy(const CapArr<T, CAP>& from) {size_ = from.size_;memcpy(data(), from.data(), sizeof(T) * from.size_);}const T* data() const {return &array_[0];}T* data() {return &array_[0];}T& front() {return array_[0];}const T& front() const {return array_[0];}T& back() {return array_[size_ - 1];}const T& back() const {return array_[size_ - 1];}T& operator[](int index) {return array_[index];}const T& operator[](int index) const {return array_[index];}T* begin() {return &array_[0];}T* end() {return &array_[size_];}const T* begin() const {return &array_[0];}const T* end() const {return &array_[size_];}[[nodiscard]] T& push() {auto& ref = array_[size_];++size_;return ref;}void push(const T& e) {array_[size_] = e;++size_;}void pop() {--size_;}int find(const T& value) const {REP(i, size_) {if (array_[i] == value) {return i;}}return -1;}bool contains(const T& value) const {for (const auto& v : *this) {if (v == value) {return true;}}return false;}void insert(int index, const T& value) {insert(index, &value, 1);}void insert(int index, const T* mem, int size) {if (index == size_) {memcpy(data() + index, mem, sizeof(T) * size);size_ += size;}else {memmove(data() + index + size, data() + index, sizeof(T) * (size_ - index));memcpy(data() + index, mem, sizeof(T) * size);size_ += size;}}template <int RCAP>void append(const CapArr<T, RCAP>& r) {insert(size(), r.data(), r.size());}void remove(int index) {remove(index, index + 1);}void remove(int start, int end) {int size = end - start;memmove(data() + start, data() + end, sizeof(T) * (size_ - end));size_ -= size;}void RemoveSwap(int index) {array_[index] = array_[size_ - 1];--size_;}void RemoveInsert(int start, int end, const T* p, int size) {int newEnd = start + size;if (size_ - end > 0 && newEnd != end) {memmove(data() + newEnd, data() + end, sizeof(T) * (size_ - end));}memcpy(data() + start, p, sizeof(T) * size);size_ -= end - start;size_ += size;}void stable_sort() {::stable_sort(begin(), end());}template <class LESS>void stable_sort(LESS&& less) {::stable_sort(begin(), end(), less);}void reverse() {::reverse(begin(), end());}};template <class T, int CAPACITY>struct CapacityQueue {private:array<T, CAPACITY> ar_ = {};int start_ = 0;int end_ = 0;public:inline void clear() {start_ = 0;end_ = 0;}inline void push(const T& v) {ar_[end_] = v;++end_;}inline T* push() {T* ptr = &ar_[end_];++end_;return ptr;}inline const T& get() const {return ar_[start_];}inline T pop() {return ar_[start_++];}inline bool empty() const {return start_ == end_;}inline bool exist() const {return start_ != end_;}inline int size() const {return end_ - start_;}inline int total_push_count() const {return end_;}const T& operator[](int i) const{return ar_[i];}int end_size() const {return end_;}int direct_start() const {return start_;}int direct_end() const {return end_;}inline auto begin() -> decltype(ar_.begin()) {return ar_.begin() + start_;}inline auto end() -> decltype(ar_.begin()) {return ar_.begin() + end_;}inline auto begin() const -> decltype(ar_.begin()) {return ar_.begin() + start_;}inline auto end() const -> decltype(ar_.begin()) {return ar_.begin() + end_;}const T& front() const {return ar_[start_];}const T& back() const {return ar_[end_ - 1];}};template <class T, int CAPACITY>using CapQue = CapacityQueue<T, CAPACITY>;template <int S>struct CheckMapS {private:array<u32, S> checked_ = {};u32 mark_ = 1;public:void Clear() {++mark_;if (mark_ == 0) {checked_ = {};++mark_;}}bool IsChecked(int i) const {return checked_[i] == mark_;}void Check(int i) {checked_[i] = mark_;}void Reset(int i) {checked_[i] = mark_ - 1;}bool operator[](int i) const {return checked_[i] == mark_;}bool operator == (const CheckMapS<S>& r) const {REP(i, S) {if (this->IsChecked(i) != r.IsChecked(i)) {return false;}}return true;}};template <class T, int S>struct CheckMapDataS {private:array<T, S> data_;array<u32, S> checked_ = {};u32 mark_ = 1;public:void Clear() {++mark_;if (mark_ == 0) {checked_ = {};++mark_;}}bool IsChecked(int i) const {return checked_[i] == mark_;}void Check(int i) {checked_[i] = mark_;}void Set(int i, const T& value) {checked_[i] = mark_;data_[i] = value;}void Reset(int i) {checked_[i] = mark_ - 1;}const T& Get(int i) const {VASSERT(checked_[i] == mark_);return data_[i];}T& Ref(int i) {VASSERT(checked_[i] == mark_);return data_[i];}const T& Ref(int i) const {VASSERT(checked_[i] == mark_);return data_[i];}T& operator[](int i) {VASSERT(checked_[i] == mark_);return data_[i];}const T& operator[](int i) const {VASSERT(checked_[i] == mark_);return data_[i];}T GetIf(int i, const T& defaultValue) const {if (checked_[i] == mark_) {return data_[i];}return defaultValue;}};template <class T, int CAP>struct CapacitySet {private:CapArr<T, CAP> elemens;CheckMapDataS<T, CAP> indexTable;public:CapacitySet() {}bool operator == (const CapacitySet<T, CAP>& r) const {if (elemens.size() != r.elemens.size()) {return false;}for (int i : elemens) {if (!r.IsContain(i)) {return false;}}return true;}constexpr int capacity() {return CAP;}void Fill() {indexTable.Clear();elemens.resize(CAP);iota(ALL(elemens), 0);REP(i, CAP) {indexTable.Set(i, i);}}void Clear() {elemens.clear();indexTable.Clear();}void Add(T ai) {indexTable.Set(ai, elemens.size());elemens.push(ai);}void ForceAdd(T ai) {if (indexTable.IsChecked(ai)) {return;}indexTable.Set(ai, elemens.size());elemens.push(ai);}void Remove(int ai) {T removeIndex = indexTable[ai];T lastIndex = elemens.size() - 1;if (removeIndex != lastIndex) {elemens[removeIndex] = elemens[lastIndex];indexTable.Set(elemens[lastIndex], removeIndex);}elemens.pop();indexTable.Reset(ai);}void ForceRemove(T ai) {if (!indexTable.IsChecked(ai)) {return;}T removeIndex = indexTable[ai];T lastIndex = elemens.size() - 1;if (removeIndex != lastIndex) {elemens[removeIndex] = elemens[lastIndex];indexTable.Set(elemens[lastIndex], removeIndex);}elemens.pop();indexTable.Reset(ai);}bool contains(T i) const {return indexTable.IsChecked(i);}bool IsContain(T i) const {return contains(i);}int size() const {return elemens.size();}bool empty() const {return elemens.empty();}T At(int index) const {return elemens[index];}T operator[](int index) const {return elemens[index];}auto begin() -> decltype(elemens.begin()) {return elemens.begin();}auto end() -> decltype(elemens.begin()) {return elemens.end();}auto begin() const -> decltype(elemens.begin()) {return elemens.begin();}auto end() const -> decltype(elemens.begin()) {return elemens.end();}};template <class T, int CAP>using CapSet = CapacitySet<T, CAP>;template <class T, int CAP>struct CapacityMap {private:CapArr<pr<int, T>, CAP> elemens;CheckMapDataS<int, CAP> indexTable;public:CapacityMap() {indexTable.Clear();}void Clear() {elemens.clear();indexTable.Clear();}inline void Add(int i, const T& value) {indexTable.Set(i, elemens.size());elemens.push({ i, value });}inline void ForceAdd(int i, const T& value) {if (indexTable.IsChecked(i)) {return;}indexTable.Set(i, elemens.size());elemens.push({ i, value });}inline void Remove(int i) {int removeIndex = indexTable[i];int lastIndex = elemens.GetCount() - 1;if (removeIndex != lastIndex) {elemens[removeIndex] = elemens[lastIndex];indexTable[elemens[lastIndex].a] = removeIndex;}elemens.pop();indexTable.Reset(i);}inline void ForceRemove(int i) {if (!indexTable.IsChecked(i)) {return;}int removeIndex = indexTable[i];int lastIndex = elemens.size() - 1;if (removeIndex != lastIndex) {elemens[removeIndex] = elemens[lastIndex];indexTable[elemens[lastIndex].a] = removeIndex;}elemens.pop();indexTable.Reset(i);}inline bool IsContain(int i) const {return indexTable.IsChecked(i);}inline int GetCount() const {return elemens.size();}inline auto begin() -> decltype(elemens.begin()) {return elemens.begin();}inline auto end() -> decltype(elemens.begin()) {return elemens.end();}inline auto begin() const -> decltype(elemens.begin()) {return elemens.begin();}inline auto end() const -> decltype(elemens.begin()) {return elemens.end();}};template <class T, int CAPACITY>using CapMap = struct CapacityMap<T, CAPACITY>;template <class IT, class RAND>void Shuffle(IT&& begin, IT&& end, RAND&& rand) {int size = int(end - begin);if (size <= 1) {return;}REP(i, size - 1) {int j = i + rand() % (size - i);swap(*(begin + i), *(begin + j));}}#include <cstdint>struct Xor64 {using result_type = uint64_t;static constexpr result_type min() { return 0; }static constexpr result_type max() { return UINT64_MAX; }private:Xor64(const Xor64& r) = delete;Xor64& operator =(const Xor64& r) = delete;public:uint64_t x;inline Xor64(uint64_t seed = 0) {x = 88172645463325252ULL + seed;}inline uint64_t operator()() {x = x ^ (x << 7);return x = x ^ (x >> 9);}inline uint64_t operator()(uint64_t l, uint64_t r) {return ((*this)() % (r - l)) + l;}template <class T>inline T operator()(T r) {return (*this)() % r;}inline double GetDouble() {return (*this)() / (double)UINT64_MAX;}inline bool GetProb(double E) {return GetDouble() <= E;}};enum class Dir : int8_t {L = 0,U,R,D,N,Invalid,};constexpr array<Dir, 4> Dir4 = {Dir::L,Dir::U,Dir::R,Dir::D,};constexpr array<pint, 4> Around4 = { pint{-1, 0}, pint{0, -1}, pint{1, 0}, pint{0, 1} };constexpr array<pint, 5> Around5 = { pint{-1, 0}, pint{0, -1}, pint{1, 0}, pint{0, 1}, pint{0, 0} };inline Dir RotateRight(Dir d) {constexpr Dir nexts[4] = {Dir::U,Dir::R,Dir::D,Dir::L,};return nexts[(int8_t)d];}inline Dir RotateLeft(Dir d) {constexpr Dir nexts[4] = {Dir::D,Dir::L,Dir::U,Dir::R,};return nexts[(int8_t)d];}inline Dir Back(Dir d) {return Dir(s8(d) ^ 2);}bool IsHorizontal(Dir dir) {return dir == Dir::L || dir == Dir::R;}bool IsVertical(Dir dir) {return dir == Dir::U || dir == Dir::D;}inline Dir CalcDir(const pint& from, const pint& to) {if (from.x > to.x) {return Dir::L;}else if (from.y > to.y) {return Dir::U;}else if (from.x < to.x) {return Dir::R;}else if (from.y < to.y) {return Dir::D;}else {return Dir::N;}}inline const string& DirString(Dir dir) {static const string strs[6] = {"LEFT","UP","RIGHT","DOWN","WAIT","INVALID",};return strs[(int)dir];}inline char DirToChar(Dir dir) {static const char chars[6] = {'L','U','R','D','N','*',};return chars[(int)dir];}inline Dir CharToDir(char c) {if (c == 'L') {return Dir::L;}else if (c == 'U') {return Dir::U;}else if (c == 'R') {return Dir::R;}else if (c == 'D') {return Dir::D;}else if (c == 'N') {return Dir::N;}VABORT();return Dir::Invalid;}template <int W, int H>struct GridSystemS {inline constexpr int ToId(int x, int y) const {return x + W * y;}inline constexpr int ToId(const pint& p) const {return p.x + W * p.y;}inline constexpr pint ToPos(int id) const {return pint{ id % W, id / W };}inline int CalcL1Dist(const pint& a, const pint& b) const {return abs(a.x - b.x) + abs(a.y - b.y);}inline int CalcL1Dist(int a, int b) const {return CalcL1Dist(ToPos(a), ToPos(b));}inline int CalcL2Dist2(const pint& a, const pint& b) const {return square(a.x - b.x) + square(a.y - b.y);}inline int CalcL2Dist2(int a, int b) const {return CalcL2Dist2(ToPos(a), ToPos(b));}inline double CalcL2Dist(const pint& a, const pint& b) const {return sqrt(CalcL2Dist2(a, b));}inline double CalcL2Dist(int a, int b) const {return CalcL2Dist(ToPos(a), ToPos(b));}inline bool IsOut(int x, int y) const {if (x < 0 || x >= W ||y < 0 || y >= H) {return true;}return false;}inline bool IsOut(const pint& p) const {return IsOut(p.x, p.y);}inline bool IsIn(const pint& p) const {return !IsOut(p);}inline int RotateRight90(int id) const {pint p = ToPos(id);return ToId(W - 1 - p.y, p.x);}inline Dir CalcDir(int from, int to) const {if (from - 1 == to) {return Dir::L;}else if (from - W == to) {return Dir::U;}else if (from + 1 == to) {return Dir::R;}else if (from + W == to) {return Dir::D;}else if (from == to) {return Dir::N;}else {VABORT();}return Dir::Invalid;}};template <class T, int CAP>struct CCA {private:T ar[CAP];int s;public:inline constexpr void push(const T& v) {ar[s++] = v;}inline constexpr void pop() {--s;}inline constexpr const T* begin() const {return &ar[0];}inline constexpr const T* end() const {return &ar[s];}inline constexpr const T& operator ()(int i) const {VASSERT(i >= 0 && i < CAP);return ar[i];}inline constexpr const T& operator [](int i) const {VASSERT(i >= 0 && i < CAP);return ar[i];}inline constexpr int size() const {return s;}};template <int W, int H, int AROUND_COUNT>struct AroundMapS {using CA = CCA<int, AROUND_COUNT>;CA table[W * H];constexpr AroundMapS(const array<pint, AROUND_COUNT>& aroundDirs) : table{} {REP(cellId, W * H) {pint p = { cellId % W, cellId / W };for (const pint& a : aroundDirs) {int x = p.a + a.a;int y = p.b + a.b;if (x >= 0 && x < W &&y >= 0 && y < H) {table[cellId].push(x + y * W);}}}}inline constexpr const CA& operator ()(int id) const {return table[id];}inline constexpr const CA& operator [](int id) const {return table[id];}};template <int W, int H, int AROUND_COUNT>struct DirMapS {using CA = CCA<int, AROUND_COUNT>;CA table[W * H];constexpr DirMapS(const array<pint, AROUND_COUNT>& aroundDirs) : table{} {REP(cellId, W * H) {pint p = { cellId % W, cellId / W };for (const pint& a : aroundDirs) {int x = p.a + a.a;int y = p.b + a.b;int n = -1;if (x >= 0 && x < W &&y >= 0 && y < H) {n = x + y * W;}table[cellId].push(n);}}}inline constexpr const CA& operator ()(int id) const {return table[id];}inline constexpr const CA& operator [](int id) const {return table[id];}};template <int W, int H>struct JointAroundMapS {using CA = CCA<int, 8>;CA table[W * H];constexpr JointAroundMapS() : table{} {REP(cellId, W * H) {pint p = { cellId % W, cellId / W };FOR(oy, -1, 2) {FOR(ox, -1, 2) {if (oy == 0 && ox == 0) {continue;}int x = p.a + ox;int y = p.b + oy;int n = -1;if (x >= 0 && x < W &&y >= 0 && y < H) {n = x + y * W;}table[cellId].push(n);}}}}inline constexpr const CA& operator ()(int id) const {return table[id];}inline constexpr const CA& operator [](int id) const {return table[id];}};template <int W, int H>struct RandAroundMapS {using CA = CCA<int, 4>;CapArr<CA, 24> table[W * H];constexpr RandAroundMapS() : table{} {REP(cellId, W * H) {pint p = { cellId % W, cellId / W };CA tmp{};for (const pint& a : Around4) {int x = p.a + a.a;int y = p.b + a.b;if (x >= 0 && x < W &&y >= 0 && y < H) {tmp.push(x + y * W);}}CapArr<int, 4> idxs;REP(i, tmp.size()) {idxs.push(i);}do {auto& t = table[cellId].push();for (int i : idxs) {t.push(tmp[i]);}} while (next_permutation(ALL(idxs)));}}template <class RAND>inline constexpr const CA& operator ()(int p, RAND& r) const {auto& tbl = table[p];return tbl[r(tbl.size())];}};constexpr GridSystemS<50, 50> gs;constexpr AroundMapS<50, 50, 4> aroundMap(Around4);constexpr DirMapS<50, 50, 4> dirMap(Around4);constexpr int N = 50;constexpr int M = 20;constexpr int NN = N*N;constexpr int NNM = NN * M;constexpr int FireRange = 20;constexpr int TurnMax = 100000;template <class T> using NArr = CapArr<T, N>;template <class T> using NNArr = CapArr<T, NN>;template <class T> using MArr = CapArr<T, M>;template <class T> using NNMArr = CapArr<T, NNM>;template <class T> using NQue = CapQue<T, N>;template <class T> using NNQue = CapQue<T, NN>;template <class T> using MQue = CapQue<T, M>;template <class T> using NNMQue = CapQue<T, NNM>;template <class T> using NSet = CapSet<T, N>;template <class T> using NNSet = CapSet<T, NN>;template <class T> using MSet = CapSet<T, M>;template <class T> using NNMSet = CapSet<T, NNM>;struct Bomb {int cost_;NNArr<int> ps_;NNArr<bool> flags_;bool CanBomb(const pint& p) const {int x = p.x + FireRange;int y = p.y + FireRange;if (gs.IsOut(x, y)) {return false;}return flags_[gs.ToId(x, y)];}bool CanBomb(int putPos, int targetPos) const {auto relPos = gs.ToPos(targetPos) - gs.ToPos(putPos);return CanBomb(relPos);}};struct Input {NNArr<char> grid_;MArr<Bomb> bombs_;NNArr<int> shops_;int buildingCount_;bool IsShop(int p) const {return grid_[p] == '@';}bool IsBuilding(int p) const {return grid_[p] == '#';}bool IsBlank(int p) const {return grid_[p] == '.';}};Input input_;#define PARAM_CATEGORY(NAME, VALUE, ...) int NAME = VALUE;#define PARAM_INT(NAME, VALUE, LOWER_VALUE, UPPER_VALUE) int NAME = VALUE;#define PARAM_DOUBLE(NAME, VALUE, LOWER_VALUE, UPPER_VALUE) double NAME = VALUE;#define PARAM_LOWER(v)#define PARAM_UPPER(v)#define START_TUNING#define END_TUNING#define PARAM_GROUP(NAME)#define PARAM_GROUP_ENDtemplate <class T>struct InputParam {T minValue_;T maxValue_;T value_;InputParam(T minValue, T maxValue) {minValue_ = minValue;maxValue_ = maxValue;}void SetValue(T value) {value_ = value;}double GetRate(double strong) const {double r = (value_ - minValue_) / (double)(maxValue_ - minValue_) * 2.0 - 1.0;return r * strong;}};static double BlendDoubleParam(double baseValue, double minValue, double maxValue, initializer_list<double> rates) {double totalRate = 1;for (double rate : rates) {totalRate += rate;}double value = baseValue * totalRate;chmax(value, minValue);chmin(value, maxValue);return value;}static int BlendIntParam(double baseValue, int minValue, int maxValue, initializer_list<double> rates) {double totalRate = 1;for (double rate : rates) {totalRate += rate;}int value = (int)round(baseValue * totalRate);chmax(value, minValue);chmin(value, maxValue);return value;}constexprstruct {START_TUNING;END_TUNING;} HP;enum class CommandType : s8 {Empty = 0,Move = 1,Buy = 2,Fire = 3,};struct IOCommand {CommandType type_;s8 value_;void SetMove(Dir dir) {type_ = CommandType::Move;value_ = (s8)dir;}void SetBuy(s8 bi) {type_ = CommandType::Buy;value_ = bi;}void SetFire(s8 bi) {type_ = CommandType::Fire;value_ = bi;}void SetEmpty() {type_ = CommandType::Empty;value_ = -1;}void Output(ostream& os) const {if (type_ == CommandType::Move) {os << (int)type_ << " " << DirToChar(Dir(value_)) << endl;}else {os << (int)type_ << " " << (int)value_ + 1 << endl;}}};struct IOResult {CapArr<IOCommand, TurnMax> commands_;IOCommand& push() {return commands_.push();}void Output(ostream& os) const {os << commands_.size() << endl;REP(i, commands_.size()) {commands_[i].Output(os);}}};struct PutPoint {int p_;int bi_;};struct TargetSystem {int ToId(int p, int bi) const {return p * M + bi;}int ToId(const PutPoint& pp) const {return pp.p_ * M + pp.bi_;}PutPoint ToPP(int id) const {return PutPoint{ id / M, id % M };}};constexpr TargetSystem ts;struct FireMap {using CA = CapArr<int, 41 * 41>;array<CA, NNM> table;void Init() {REP(p, NN) {REP(bi, M) {int tid = ts.ToId(p, bi);for (int op : input_.bombs_[bi].ps_) {pint pos = gs.ToPos(op);pos.x -= FireRange;pos.y -= FireRange;pos += gs.ToPos(p);if (gs.IsOut(pos)) {continue;}int id = gs.ToId(pos);if (input_.IsBlank(id)) {continue;}table[tid].push(id);}}}}inline const CA& operator [](int tid) const {return table[tid];}};struct FromFireMap {using CA = CapArr<int, 41 * 41 * M>;array<CA, NN> table;void Init() {REP(p, NN) {if (input_.IsBlank(p)) {continue;}REP(bi, M) {for (int op : input_.bombs_[bi].ps_) {pint pos = gs.ToPos(op);pos.x -= FireRange;pos.y -= FireRange;pos = -pos;pos += gs.ToPos(p);if (gs.IsOut(pos)) {continue;}int tid = ts.ToId(gs.ToId(pos), bi);table[p].push(tid);}}}}inline const CA& operator [](int p) const {return table[p];}};FireMap fireMap;FromFireMap fromFireMap;struct IOServer {void InitInput(ChronoTimer& timer) {istream& is = cin;int dummy;is >> dummy >> dummy;timer.Init();input_.buildingCount_ = 0;auto& grid = input_.grid_;grid.resize(NN);REP(i, NN) {is >> grid[i];if (grid[i] == '@') {input_.shops_.push(i);}if (grid[i] == '#') {++input_.buildingCount_;}}auto& bombs = input_.bombs_;bombs.resize(M);REP(i, M) {auto& bomb = bombs[i];is >> bomb.cost_;int L;is >> L;bomb.ps_.resize(L);bomb.flags_.assign(NN, false);REP(j, L) {int a, b;is >> a >> b;a += FireRange;b += FireRange;int id = gs.ToId(b, a);bomb.ps_[j] = id;bomb.flags_[id] = true;}}fireMap.Init();fromFireMap.Init();}void Output(const IOResult& result) {ostream& os = cout;result.Output(os);}void Finalize() {}};IOServer server;#define USE_SA_POINT_FILTER 1#define USE_SA_ROLLBACK 1constexpr int InitialStateCount = 1;struct RandomTable {vector<int> table_;void push(int value, int count) {table_.reserve(table_.size() + count);REP(i, count) {table_.emplace_back(value);}}template <class ENGINE>int operator()(ENGINE& engine) {return table_[engine() % table_.size()];}};struct SAChecker {Xor64* rand_ = nullptr;double* totalMaxScore_ = nullptr;double temp = 0;double divTemp = 0;double currentScore = 0;double maxScore = 0;int noMaxUpdateCount = 0;int nextRollbackCheckCount = INT_MAX;#if USE_ACCEPT_SCOREinline bool operator()(double newScore, bool forceUpdate = false) {#elseinline bool operator()(double newScore) {#endif++noMaxUpdateCount;if (newScore > currentScore) {currentScore = newScore;if (newScore > maxScore) {maxScore = newScore;noMaxUpdateCount = 0;if (newScore > *totalMaxScore_) {*totalMaxScore_ = newScore;}}return true;}else if (newScore == currentScore) {return true;}else {#if USE_ACCEPT_SCOREif (forceUpdate || exp((newScore - currentScore) * divTemp) * UINT32_MAX > (*rand_)(UINT32_MAX)) {#elseif (exp((newScore - currentScore) * divTemp) * UINT32_MAX > (*rand_)(UINT32_MAX)) {#endifcurrentScore = newScore;return true;}else {return false;}}}#if USE_ACCEPT_SCOREdouble AcceptScore() {static_assert(numeric_limits<double>::is_iec559);return currentScore + temp * log(rand_->GetDouble());}void SetRevert() {++noMaxUpdateCount;}#endif};template <class F>struct SATransition {const char* name;F func;int weight;};template <class F>auto MakeTransition(const char* name, F&& func, int weight) {return SATransition<F>{ name, func, weight };}#define MAKE_TRANS(func, weight) MakeTransition(#func, [&](SAChecker& sac, State& state) { func(sa, sac, state); }, weight)struct SimulatedAnnealing {vector<SAChecker> checkers;double totalMaxScore = 0;double timeRate = 0;double temp = 0;double divTemp = 0;Xor64 rand_;double startTemp_ = 200;double endTemp_ = 1;int stepLoopCount = 1000;double rollbackStartRate_ = 999.0;int rollbackCount_ = INT_MAX;double rollbackNextMulti_ = 1.1;int minRollbackCount_ = 1;public:template <class STATE, class... TRANSITION>void Run2(ChronoTimer& timer, vector<STATE>& states, tuple<SATransition<TRANSITION>...>& transitions) {vector<STATE> maxStates = states;checkers.resize(states.size());totalMaxScore = states[0].EvalScore();REP(pi, checkers.size()) {auto& checker = checkers[pi];checker.rand_ = &rand_;checker.totalMaxScore_ = &totalMaxScore;checker.temp = 0;checker.divTemp = 0;checker.currentScore = states[pi].EvalScore();checker.maxScore = checker.currentScore;checker.noMaxUpdateCount = 0;checker.nextRollbackCheckCount = rollbackCount_;chmax(totalMaxScore, checker.maxScore);}RandomTable randTable;TupleLoop(transitions, [&](auto&& e, size_t i) {randTable.push((int)i, e.weight);});const auto startTime = timer.Now();const auto endTime = timer.EndTime();const double subTimeCountDiv = 1.0 / (double)(endTime - startTime).count();vector<int> pis(states.size());iota(ALL(pis), 0);bool forceEnd = false;while (!timer.IsOver()) {timeRate = (timer.Now() - startTime).count() * subTimeCountDiv;temp = startTemp_ * std::pow(endTemp_ / startTemp_, timeRate);divTemp = 1.0 / temp;for (auto& checker : checkers) {checker.temp = temp;checker.divTemp = divTemp;}for (int rp = 0; rp < stepLoopCount; ++rp) {int ti = (int)randTable(rand_);auto exec = [&](auto&& e, size_t i) {for (int pi : pis) {auto& checker = checkers[pi];e.func(checker, states[pi]);if (states[pi].RawScore() > maxStates[pi].RawScore()) {maxStates[pi] = states[pi];}else {if (timeRate >= rollbackStartRate_) {if (checker.noMaxUpdateCount >= checker.nextRollbackCheckCount) {states[pi] = maxStates[pi];checker.noMaxUpdateCount = 0;checker.nextRollbackCheckCount = (int)round(checker.nextRollbackCheckCount * rollbackNextMulti_);chmax(checker.nextRollbackCheckCount, minRollbackCount_);}}}}};TupleAccess(transitions, ti, exec);}if (forceEnd) {break;}{constexpr double start = 0.2;constexpr double end = 1.0;int targetPointCount = (int)states.size();if (timeRate >= end) {targetPointCount = 1;}else if (timeRate >= start) {double r = 1.0 - (timeRate - start) / (end - start);targetPointCount = 1 + (int)floor(states.size() * r);}if ((int)pis.size() > targetPointCount) {sort(ALL(pis), [&](int a, int b) {return checkers[a].maxScore > checkers[b].maxScore;});pis.resize(targetPointCount);}}}}void ForceUpdate() {}private:template <class Tuple, class Func>void TupleLoop(Tuple & t, Func && f) {TupleLoop2(t, forward<Func>(f), make_index_sequence<tuple_size<Tuple>::value>{});}template <class Tuple, class Func, size_t... Indics>void TupleLoop2(Tuple & t, Func && f, index_sequence<Indics...>) {using swallow = int[];(void)swallow {(TupleLoop3<Tuple, Func, Indics>(t, f), 0)...};}template <class Tuple, class Func, size_t Index>void TupleLoop3(Tuple & t, Func & f) {f(get<Index>(t), Index);}template <class Tuple, class Func>void TupleAccess(Tuple & t, int i, Func && f) {TupleAccess2(t, i, forward<Func>(f), make_index_sequence<tuple_size<Tuple>::value>{});}template <class Tuple, class Func, size_t... Indics>void TupleAccess2(Tuple & t, int i, Func && f, index_sequence<Indics...>) {using swallow = int[];(void)swallow {(TupleAccess3<Tuple, Func, Indics>(t, i, f), 0)...};}template <class Tuple, class Func, size_t Index>void TupleAccess3(Tuple & t, int i, Func & f) {if (i == Index) {f(get<Index>(t), Index);}}};Xor64 rand_;struct Backup {};struct PlanState {NNArr<int> orderdSis_;NNMArr<int> breakableCount_;NNMSet<int> breakableTids_;NNMSet<int> tids_;NNArr<int> firedCount_;void Init() {orderdSis_.clear();orderdSis_.Iota(input_.shops_.size());breakableCount_.assign(NNM, 0);breakableTids_.Clear();REP(i, NN) {if (!input_.IsBlank(i)) {UpdateRefCountWithBuild(i);}}tids_.Clear();firedCount_.assign(NN, 0);}bool IsEnd() const {return breakableTids_.empty();}void Put(int p, int bi) {int tid = ts.ToId(p, bi);tids_.Add(tid);for (int id : fireMap[tid]) {VASSERT(!input_.IsBlank(id));++firedCount_[id];if (firedCount_[id] == 1) {UpdateRefCountWithBreak(id);}}}void Remove(int tid) {auto pp = ts.ToPP(tid);for (int id : fireMap[tid]) {VASSERT(!input_.IsBlank(id));--firedCount_[id];if (firedCount_[id] == 0) {UpdateRefCountWithBuild(id);}}tids_.Remove(tid);}int GetBreakCount(int p, int bi) const {return breakableCount_[ts.ToId(p, bi)];}void UpdateRefCountWithBreak(int p) {VASSERT(!input_.IsBlank(p));for (int tid : fromFireMap[p]) {--breakableCount_[tid];VASSERT(breakableCount_[tid] >= 0);if (breakableCount_[tid] == 0) {breakableTids_.Remove(tid);}}}void UpdateRefCountWithBuild(int p) {VASSERT(!input_.IsBlank(p));for (int tid : fromFireMap[p]) {++breakableCount_[tid];if (breakableCount_[tid] == 1) {breakableTids_.Add(tid);}}}void RemoveUnnecessary() {auto IsRequire = [&](int tid) {auto pp = ts.ToPP(tid);for (int id : fireMap[tid]) {VASSERT(!input_.IsBlank(id));if (firedCount_[id] == 1) {return true;}}return false;};NNMArr<int> notRequires;for (int tid : tids_) {if (!IsRequire(tid)) {notRequires.push(tid);}}Shuffle(ALL(notRequires), rand_);while (true) {bool updated = false;for (int tid : notRequires) {if (tids_.IsContain(tid)) {if (!IsRequire(tid)) {Remove(tid);updated = true;}}}if (!updated) {break;}}}void FillGreedy() {const int lastShop = input_.shops_[orderdSis_.back()];bool brokenLastShop = firedCount_[lastShop] > 0;while (!breakableTids_.empty()) {int bestTo = -1;int bestBi = -1;bool bestBreakLastShop = false;double bestEval = -1e100;for (int tid : breakableTids_) {PutPoint pp = ts.ToPP(tid);int i = pp.p_;int bi = pp.bi_;bool breakLastShop = false;{breakLastShop = input_.bombs_[bi].CanBomb(pp.p_, lastShop);if (brokenLastShop && breakLastShop) {continue;}}int count = GetBreakCount(pp.p_, pp.bi_);VASSERT(count > 0);double eval = 0;eval += count;if (eval > bestEval) {bestEval = eval;bestTo = i;bestBi = bi;bestBreakLastShop = breakLastShop;}}VASSERT(bestTo >= 0);Put(bestTo, bestBi);if (bestBreakLastShop) {brokenLastShop = true;}}RemoveUnnecessary();}void FillRandom() {const int lastShop = input_.shops_[orderdSis_.back()];bool brokenLastShop = firedCount_[lastShop] > 0;while (!breakableTids_.empty()) {int bestTo = -1;int bestBi = -1;bool bestBreakLastShop = false;REP(loop, 1000) {int ti = rand_(breakableTids_.size());int tid = breakableTids_[ti];PutPoint pp = ts.ToPP(tid);bool breakLastShop = false;{breakLastShop = input_.bombs_[pp.bi_].CanBomb(pp.p_, lastShop);if (brokenLastShop && breakLastShop) {continue;}}VASSERT(GetBreakCount(pp.p_, pp.bi_) > 0);bestTo = pp.p_;bestBi = pp.bi_;bestBreakLastShop = breakLastShop;break;}Put(bestTo, bestBi);if (bestBreakLastShop) {brokenLastShop = true;}}RemoveUnnecessary();}};void LocalSearch2opt(const NNArr<NNArr<int>>& sortedTbl, NNArr<int>& route, NNArr<int>& order) {cauto& shops = input_.shops_;auto Cost = [&](int a, int b) {return gs.CalcL1Dist(shops[a], shops[b]);};int totalCost = 0;REP(i, route.size() - 1) {totalCost += Cost(route[i], route[i + 1]);}auto Update = [&](int iA, int iC) {int iB = iA + 1;int iD = iC + 1;int A = route[iA];int B = route[iB];int C = route[iC];int D = route[iD];if (B == C || A == D || B == D) {return false;}if (Cost(A, B) + Cost(C, D) > Cost(A, C) + Cost(B, D)) {int newDist = totalCost - (Cost(A, B) + Cost(C, D)) + (Cost(A, C) + Cost(B, D));totalCost = newDist;if (iB > iD) {swap(iB, iD);}reverse(route.begin() + iB, route.begin() + iD);FOR(i, iB, iD) {order[route[i]] = i;}return true;}return false;};while (true) {bool update = false;REP(iA, shops.size() - 1) {int iB = iA + 1;for (u8 C : sortedTbl[route[iA]]) {int iC = order[C];if (iC == iB) {break;}if (iC == shops.size() - 1) {continue;}if (Update(iA, iC)) {update = true;break;}}if (update) {break;}for (u8 D : sortedTbl[route[iB]]) {int iD = order[D];if (iD == iA) {break;}if (iD == shops.size() - 1) {continue;}if (iD == 0) {continue;}int iC = iD - 1;if (Update(iA, iC)) {update = true;break;}}if (update) {break;}}if (!update) {break;}}}void CalcShopOrder(NNArr<int>& orderdSis) {orderdSis.clear();cauto& shops = input_.shops_;NNArr<bool> used;used.assign(shops.size(), false);int p = 0;REP(loop, shops.size()) {int bestD = INT_MAX;int bestI = -1;REP(i, shops.size()) {if (used[i]) {continue;}int s = shops[i];int d = gs.CalcL1Dist(p, shops[i]);if (d < bestD) {bestD = d;bestI = i;}}VASSERT(bestI >= 0);p = shops[bestI];used[bestI] = true;orderdSis.push(bestI);}static NNArr<NNArr<int>> aroundSortedSis;aroundSortedSis.resize(shops.size());REP(siA, shops.size()) {auto& sis = aroundSortedSis[siA];REP(siB, shops.size()) {if (siA == siB) {continue;}sis.push(siB);}sis.stable_sort([&](int a, int b) {return gs.CalcL1Dist(shops[siA], shops[a]) < gs.CalcL1Dist(shops[siA], shops[b]);});}NNArr<int> order;order.resize(orderdSis.size());REP(i, orderdSis.size()) {order[orderdSis[i]] = i;}LocalSearch2opt(aroundSortedSis, orderdSis, order);}void MakePlan(PlanState& plan) {plan.Init();CalcShopOrder(plan.orderdSis_);plan.FillGreedy();}struct MoveState {int p_;NNArr<char> grid_;int shopCount_;int buildingCount_;int bombCount_;MArr<int> bombCounts_;s64 cost_;void Init() {p_ = 0;grid_ = input_.grid_;shopCount_ = input_.shops_.size();buildingCount_ = input_.buildingCount_;bombCount_ = 0;bombCounts_.assign(M, 0);cost_ = 0;}s64 Score() const {if (shopCount_ > 0 || buildingCount_ > 0) {return 1;}return max(10LL, 1000000000000LL / (10000LL + cost_));}bool IsEnd() const {return shopCount_ == 0 && buildingCount_ == 0;}void Move(int p, IOResult& result) {pint cur = gs.ToPos(p_);pint to = gs.ToPos(p);int dx = to.x - cur.x;int dy = to.y - cur.y;Dir dirX = dx > 0 ? Dir::R : Dir::L;Dir dirY = dy > 0 ? Dir::D : Dir::U;if (dx > 0) {dx = 1;}else if (dx < 0) {dx = -1;}if (dy > 0) {dy = 1;}else if (dy < 0) {dy = -1;}while (cur.x != to.x) {cur.x += dx;result.push().SetMove(dirX);if (grid_[gs.ToId(cur)] == '.') {cost_ += square(bombCount_ + 1);} else {cost_ += 2 * square(bombCount_ + 1);}}while (cur.y != to.y) {cur.y += dy;result.push().SetMove(dirY);if (grid_[gs.ToId(cur)] == '.') {cost_ += square(bombCount_ + 1);}else {cost_ += 2 * square(bombCount_ + 1);}}p_ = p;}void Buy(int bi, IOResult& result) {VASSERT(grid_[p_] == '@');++bombCount_;++bombCounts_[bi];cost_ += input_.bombs_[bi].cost_;result.push().SetBuy(bi);}void Fire(int bi, IOResult& result) {VASSERT(bombCounts_[bi] > 0);--bombCount_;--bombCounts_[bi];WarpFire(p_, bi);result.push().SetFire(bi);}void WarpFire(int p, int bi) {for (int id : fireMap[ts.ToId(p, bi)]) {char c = grid_[id];if (c != '.') {if (c == '@') {--shopCount_;}else {VASSERT(c == '#');--buildingCount_;}grid_[id] = '.';}}}};void MakeMove(const PlanState& plan, IOResult& result, s64& cost) {MoveState state;state.Init();int targetSii = 0;cauto& shops = input_.shops_;cauto& orderdSis = plan.orderdSis_;auto planTids = plan.tids_;while (targetSii < orderdSis.size()) {const int targetSi = orderdSis[targetSii];const int targetShop = shops[targetSi];if (state.grid_[targetShop] == '.') {++targetSii;continue;}NNArr<int> posToSi;NNArr<int> posToSiDist;NNArr<int> enableTids;NNArr<int> finalTids;posToSi.assign(NN, -1);posToSiDist.assign(NN, INT_MAX);for (int tid : planTids) {PutPoint pp = ts.ToPP(tid);if (posToSi[pp.p_] < 0) {int bestD = INT_MAX;int bestSi = -1;FOR(sii, targetSii, orderdSis.size()) {int si = orderdSis[sii];int sp = shops[si];if (state.grid_[sp] == '.') {continue;}int d = gs.CalcL1Dist(pp.p_, sp);if (d < bestD) {bestD = d;bestSi = si;}}VASSERT(bestSi >= 0);posToSi[pp.p_] = bestSi;posToSiDist[pp.p_] = bestD;}if (posToSi[pp.p_] == targetSi) {if (targetSii + 1 != orderdSis.size()) {int lastShop = shops[orderdSis.back()];if (input_.bombs_[pp.bi_].CanBomb(pp.p_, lastShop)) {continue;}}if (input_.bombs_[pp.bi_].CanBomb(pp.p_, targetShop)) {finalTids.push(tid);}else {enableTids.push(tid);}}}if (enableTids.size()) {for (int tid : enableTids) {auto pp = ts.ToPP(tid);state.Move(targetShop, result);state.Buy(pp.bi_, result);state.Move(pp.p_, result);state.Fire(pp.bi_, result);planTids.Remove(tid);}continue;}VASSERT(targetSii + 1 != orderdSis.size() || finalTids.size() == 1);finalTids.stable_sort([&](int a, int b) {return posToSiDist[ts.ToPP(a).p_] > posToSiDist[ts.ToPP(b).p_];});for (int tid : finalTids) {auto pp = ts.ToPP(tid);state.Move(targetShop, result);state.Buy(pp.bi_, result);state.Move(pp.p_, result);state.Fire(pp.bi_, result);planTids.Remove(tid);break;}++targetSii;}VASSERT(state.IsEnd());cost = state.cost_;}struct State {PlanState plan_;s64 rawScore_;void Init() {plan_.Init();MakePlan(plan_);IOResult result;s64 cost;MakeMove(plan_, result, cost);rawScore_ = cost;}s64 RawScore() const {return -rawScore_;}double EvalScore() const {return (double)-rawScore_;}};static constexpr int StateSize = sizeof(State);struct Solver {State maxState_;void CheckMaxScore(const State& state) {if (state.RawScore() > maxState_.RawScore()) {maxState_ = state;}}void Run(ChronoTimer& timer) {vector<State> states;InitState(states);maxState_ = states[0];SimulatedAnnealing sa;sa.startTemp_ = 100;sa.endTemp_ = 1;sa.stepLoopCount = 10;sa.rollbackStartRate_ = 0.1;sa.rollbackCount_ = 10000;sa.rollbackNextMulti_ = 1.1;sa.minRollbackCount_ = 100;auto transitions = make_tuple(MAKE_TRANS(Transition_Update1, 10));sa.Run2(timer, states, transitions);s64 cost = 0;IOResult result;MakeMove(maxState_.plan_, result, cost);server.Output(result);}void InitState(vector<State>& states) {states.resize(InitialStateCount);{State& state = states[0];state.Init();}FOR(i, 1, InitialStateCount) {states[i] = states[0];}}void Transition_Update1(SimulatedAnnealing& sa, SAChecker& checker, State& state) {State backup = state;int removeCount = min(1 + rand_(8), state.plan_.tids_.size());REP(i, removeCount) {int ti = rand_(state.plan_.tids_.size());int tid = state.plan_.tids_[ti];state.plan_.Remove(tid);}state.plan_.FillGreedy();s64 cost = 0;IOResult result;MakeMove(state.plan_, result, cost);double newEvalScore = (double) - cost;if (checker(newEvalScore)) {state.rawScore_ = cost;CheckMaxScore(state);}else {state = backup;}}};struct Main {void Run(int argc, const char* argv[]) {ChronoTimer timer;server.InitInput(timer);static Solver solver;timer.StartMs(TIME_LIMIT);solver.Run(timer);server.Finalize();}};