Submission #63336637
Source Code Expand
#include <vector>
#include <string>
#include <algorithm>
#include <complex>
#include <utility>
#include <unordered_map>
#include <optional>
#include <functional>
#include <deque>
#include <cmath>
#include <iostream>
namespace visualizer {
using std::string;
using std::vector;
using std::optional;
using std::nullopt;
using Point = std::complex<double>;
#define VISUALIZE // 提出時にはここをコメントアウトすること。そうしないとTLEする。
#if (defined(ONLINE_JUDGE) || defined(ATCODER) || defined(NOVIS)) && defined(VISUALIZE)
constexpr bool DO_NOT_VISUALIZE = 1;
#undef VISUALIZE // 誤提出防止
#endif
namespace vis_internal {
FILE* visFile = nullptr;
Point visualizer_campus_size;
bool visualizer_internal_y_upper = false;
// constexpr int MAX_HIST_LEN = 100*100*3*10000;
constexpr int MAX_HIST_LEN = 0x7fffffff;
std::deque<std::size_t> hash_hist;
constexpr int buf_len = 2048;
char buf[buf_len];
int buf_i = 0;
long long line_number = 1;
std::size_t get_buf_hash() {
std::size_t hash = buf_i;
const char* str = buf;
while (*str) {
hash ^= static_cast<std::size_t>(*str++) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
std::unordered_map<std::size_t, long long> compressor;
long long start_same_line = -1;
long long last_same_line = -1;
inline void pop_line_combo() {
if (start_same_line == -1) return;
if (start_same_line == last_same_line) {
fprintf(visFile, "L%lld\n", start_same_line);
} else {
fprintf(visFile, "L%lld:%lld\n", start_same_line, last_same_line-start_same_line+1);
}
start_same_line = last_same_line = -1;
}
int max_vtime = 0;
bool vis_time_enable = true;
int vis_time_interval = 1;
}
void set_vis_time_interval(int interval = 1) {
vis_internal::vis_time_interval = interval;
}
#ifdef VISUALIZE
constexpr bool DO_NOT_VISUALIZE = 0;
#define VRET ;
template<typename... Args>
void print(const char* format, Args... args) {
VRET;
using namespace vis_internal;
if (vis_time_enable == false) {
return;
}
if constexpr (sizeof...(args) > 0) {
buf_i += std::snprintf(buf + buf_i, buf_len - buf_i, format, args...);
} else {
buf_i += std::snprintf(buf + buf_i, buf_len - buf_i, "%s", format);
}
if (buf[buf_i-1] != '\n') return;
++line_number;
bool ignore = (buf[0] == '<' && buf[1] == '!');
static bool warned = false;
if (line_number >= 0x7fff'ffff && !warned) [[unlikely]] {
fprintf(stderr, "SVG command number exceeds INT32_MAX.\n");
std::fflush(stderr);
warned = true;
return;
}
if (ignore) {
pop_line_combo();
fprintf(visFile, "%s", buf);
} else {
std::size_t hash = get_buf_hash();
auto it = compressor.find(hash);
if (it == compressor.end() || true) {
compressor.emplace(hash, line_number);
hash_hist.emplace_back(hash);
pop_line_combo();
fprintf(visFile, "%s", buf);
} else {
if (start_same_line == -1) {
start_same_line = last_same_line = it->second;
} else if (last_same_line + 1 == it->second) {
last_same_line = it->second;
} else {
pop_line_combo();
start_same_line = last_same_line = it->second;
}
it->second = line_number;
hash_hist.emplace_back(hash);
}
// if (hash_hist.size() >= MAX_HIST_LEN) {
// std::size_t old_hash = hash_hist.front(); hash_hist.pop_front();
// auto it = compressor.find(old_hash);
// if (line_number - it->second >= MAX_HIST_LEN) {
// compressor.erase(it);
// }
// }
}
buf_i = 0;
}
struct visualizer_helper {
struct StringLike {
string str;
StringLike(const char* str) : str(str){}
StringLike(string str) : str(str){}
template<typename... Args> StringLike(Args... args) {
size_t size = snprintf(nullptr, 0, args...) + 1;
vector<char> buf(size);
snprintf(buf.data(), size, args...);
str = string(buf.data(), buf.data() + size - 1);
}
};
visualizer_helper(StringLike filename, Point size, Point origin = Point(), bool y_upper = false) {
init(filename.str, size, origin, y_upper);
}
visualizer_helper(Point size, Point origin = Point(), bool y_upper = false) {
init("VisCommands.svg", size, origin, y_upper);
}
void init(string filename, Point size, Point origin = Point(), bool y_upper = false) {
using namespace vis_internal;
if (size.imag() <= 0) { size.imag(size.real()); }
visualizer_campus_size = size;
visFile = fopen(filename.c_str(), "w");
fprintf(visFile, "<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='800' viewBox='%g %g %g %g'",
origin.real(), origin.imag(), size.real(), size.imag());
if (y_upper) {
visualizer_internal_y_upper = true;
fprintf(visFile, " transform='scale(1, -1)' transform-origin='0 %g'", size.imag()/2);
fprintf(visFile, "><style>text {transform: scale(1, -1);}</style");
}
fprintf(visFile, ">\n");
}
~visualizer_helper(){
print("</svg>\n");
fclose(vis_internal::visFile);
}
};
#else
#define VRET return;
struct visualizer_helper { template<typename... Args> visualizer_helper(Args... args) {} };
template<typename... Args>
void print(const char* format, Args... args) { return; }
#endif
struct Vopt {
struct v {
optional<string> fill = nullopt;
optional<string> stroke = nullopt;
optional<float> swidth = nullopt;
optional<string> text_anchor = nullopt;
optional<string> dominant_baseline = nullopt;
optional<string> title = nullopt;
optional<string> desc_text = nullopt;
optional<int16_t> z = nullopt;
} v;
Vopt(){};
Vopt(const Vopt& op) : v{op.v} {};
Vopt(const string fill) { v.fill = fill; }
Vopt(const char* fill) { v.fill = fill; }
Vopt(const string stroke, double width) { v.fill = ""; v.stroke = stroke; v.swidth = width; }
Vopt(const char* stroke, double width) { v.fill = ""; v.stroke = stroke; v.swidth = width; }
Vopt(const string fill, const string stroke, double width) { v.fill = fill; v.stroke = stroke; v.swidth = width; }
Vopt(const char* fill, const char* stroke, double width) { v.fill = fill; v.stroke = stroke; v.swidth = width; }
void p(const optional<string>& a, const char* label, const string empty = "") {
if(a) print(" %s='%s'", label, (a.value().size() ? a.value() : empty).c_str());
}
void p(const optional<float>& a, const char* label) {
if(a) print(" %s='%g'", label, a.value());
}
void operator()(bool close = true) {
VRET;
p(v.fill, "fill", "none");
p(v.stroke, "stroke");
p(v.swidth, "stroke-width");
p(v.text_anchor, "text-anchor");
p(v.dominant_baseline, "dominant-baseline");
if(v.desc_text) { print(" data-txt='%s'", v.desc_text.value().c_str()); }
if(v.title) { print("/></g>\n"); if(!close){ printf("Error! %s:%d\n", __FILE__, __LINE__); abort(); } }
else { if(close) print("/>\n"); }
}
void pre() {
VRET;
if(v.z) { print("z%d", v.z.value()); }
if(v.title) { print("<g><title>%s</title>", v.title.value().c_str()); }
}
Vopt fill(string s) { Vopt res(*this); res.v.fill = s; return res; }
Vopt stroke(string s) { Vopt res(*this); res.v.stroke = s; return res; }
Vopt swidth(float a) { Vopt res(*this); res.v.swidth = a; return res; }
Vopt stroke(string s, float v) { return stroke(s).swidth(v); }
Vopt title(string s) { Vopt res(*this); res.v.title = s; return res; }
Vopt desc(string s) { Vopt res(*this); res.v.desc_text = s; return res; }
Vopt z(int16_t z) { Vopt res(*this); res.v.z = z; return res; }
template<typename T> optional<T>& over_write(optional<T>& a, const optional<T>& g) {
if(!a && g) a = g;
return a;
}
};
Vopt fill(string s) { Vopt op; return op.fill(s); }
Vopt stroke(string s) { Vopt op; return op.stroke(s); }
Vopt swidth(float a) { Vopt op; return op.swidth(a); }
Vopt stroke(string s, float v) { Vopt op; return op.stroke(s, v); }
string color(double val) {
if constexpr (DO_NOT_VISUALIZE) return "";
val = std::clamp(val, 0.0, 1.0);
double r, g, b;
if(val < 0.5) {
double x = val * 2.0;
r = std::round(30.0 * (1.0 - x) + 144.0 * x);
g = std::round(144.0 * (1.0 - x) + 255.0 * x);
b = std::round(255.0 * (1.0 - x) + 30.0 * x);
} else {
double x = val * 2.0 - 1.0;
r = std::round(144.0 * (1.0 - x) + 255.0 * x);
g = std::round(255.0 * (1.0 - x) + 30.0 * x);
b = std::round(30.0 * (1.0 - x) + 70.0 * x);
}
char buffer[8];
std::sprintf(buffer, "#%02x%02x%02x", int(r), int(g), int(b));
return std::string(buffer);
}
void circle(Point c, float r, Vopt op = {}) { VRET;
op.pre();
print("<circle cx='%g' cy='%g' r='%g'", c.real(), c.imag(), r);
op();
}
void circles(const vector<Point>& cs, float r, Vopt op = {}) { VRET;
for(auto p : cs) circle(p, r, op);
}
void line(Point p1, Point p2, Vopt op = {}) { VRET;
op.pre();
if(op.v.fill && !op.v.stroke && !op.v.swidth) {
op.v.stroke.swap(op.v.fill);
op.v.swidth = 1;
}
print("<line x1='%g' y1='%g' x2='%g' y2='%g' stroke-linecap='round' stroke-linejoin='round'", p1.real(), p1.imag(), p2.real(), p2.imag());
op();
}
void rect(Point p, Point size, Vopt op = {}) { VRET;
op.pre();
print("<rect x='%g' y='%g' width='%g' height='%g'", p.real(), p.imag(), size.real(), size.imag());
op();
}
void rect2p(Point p, Point q, Vopt op = {}) { VRET;
rect(p, q-p, op);
}
void rectc(Point c, Point size, float deg = 0, Vopt op = {}) { VRET;
const Point p = c - size * 0.5;
op.pre();
print("<rect x='%g' y='%g' width='%g' height='%g' transform='rotate(%g %g %g)'",
p.real(), p.imag(), size.real(), size.imag(), deg, c.real(), c.imag());
op();
}
void polygon(const std::vector<Point>& ps, Vopt op = {}) { VRET;
op.pre();
print("<polygon points='");
for(auto p : ps) print("%g,%g ", p.real(), p.imag());
print("' ");
op();
}
void polyline(const std::vector<Point>& ps, Vopt op = {}) { VRET;
op.pre();
print("<polyline points='");
for(auto p : ps) print("%g,%g ", p.real(), p.imag());
print("'");
op();
}
void text(Point p, string str, float size, Vopt op = {}) { VRET;
op.pre();
print("<text x='%g' y='%g' font-size='%g'", p.real(), p.imag(), size);
if(vis_internal::visualizer_internal_y_upper) { print(" transform-origin='%g %g'", p.real(), p.imag()); }
op(false);
print(">%s</text>\n", str.c_str());
}
void text(Point p, int num, float size, Vopt op = {}) { VRET;
text(p, std::to_string(num), size, op);
}
void text(Point p, double num, float size, Vopt op = {}) { VRET;
text(p, std::to_string(num), size, op);
}
Vopt align(string align) {
Vopt op;
if constexpr (DO_NOT_VISUALIZE) return op;
if(align.find("R") != string::npos) { op.v.text_anchor = "end"; }
else if(align.find("L") != string::npos) { op.v.text_anchor = "start"; }
else { op.v.text_anchor = "middle"; }
if(align.find("T") != string::npos || align.find("U") != string::npos) { op.v.dominant_baseline = "hanging "; }
else if(align.find("B") != string::npos || align.find("D") != string::npos) { op.v.dominant_baseline = "text-bottom"; }
else if(align.find("I") != string::npos) { op.v.dominant_baseline = "ideographic"; }
else { op.v.dominant_baseline = "middle"; }
return op;
}
const Vopt alignC = align("");
void vtime(int a = -1, int b = -1){ VRET;
using namespace vis_internal;
max_vtime = std::max(std::max(max_vtime, a), b);
if(vis_internal::vis_time_interval == 1 || a == -1) {
vis_internal::vis_time_enable = true;
if(b < 0) return print("<!--time=%d-->\n", a);
else return print("<!--time=%d:%d-->\n", a, b);
} else if(b == -1) {
if(a % vis_internal::vis_time_interval == 0) {
a /= vis_internal::vis_time_interval;
vis_internal::vis_time_enable = true;
return print("<!--time=%d-->\n", a);
} else {
vis_internal::vis_time_enable = false;
}
} else {
a = (a + vis_internal::vis_time_interval) / vis_internal::vis_time_interval;
b /= vis_internal::vis_time_interval;
if(a > b) { vis_internal::vis_time_enable = false; return; }
else if(a == b) { print("<!--time=%d-->\n", a); }
else { print("<!--time=%d:%d-->\n", a, b); }
vis_internal::vis_time_enable = true;
}
}
namespace internal {
struct Segment : public std::pair<Point, Point>{
Segment(const Point &p1, const Point &p2) : std::pair<Point, Point>(p1, p2) {}
};
struct Box {
Point p, s;
Box(Point p, Point s) : p(p), s(s) {}
Point center() const { return p + s * 0.5; }
operator Point() const { return center(); }
Point UpLeft() const { return p; }
Point UpRight() const { return p + Point(s.real(), 0); }
Point BtLeft() const { return p + Point(0, s.imag()); }
Point BtRight() const { return p + s; }
Segment segL() const { return Segment(UpLeft(), BtLeft()); }
Segment segR() const { return Segment(UpRight(), BtRight()); }
Segment segU() const { return Segment(UpLeft(), UpRight()); }
Segment segD() const { return Segment(BtLeft(), BtRight()); }
Box shrink(double v) const { return {p + Point(v, v), s - Point(v*2, v*2)}; }
};
void line(const Segment& seg, Vopt op = {}) { VRET; line(seg.first, seg.second, op); }
void line(const Box& box, Vopt op = {}) { VRET;
line(box.UpLeft(), box.UpRight(), op);
line(box.UpRight(), box.BtRight(), op);
line(box.BtRight(), box.BtLeft(), op);
line(box.BtLeft(), box.UpLeft(), op);
}
void rect(const Box& box, Vopt op = {}) { VRET; rect(box.p, box.s, op); }
}
struct Grid {
int W_num = 0, H_num = 0;
Point whole_size{-1, -1}, origin{};
double cell_w = 0, cell_h = 0;
Point cell_sz{};
Grid(int WH_num) : W_num(WH_num), H_num(WH_num) { init(); }
Grid(int W_num, int H_num, Point whole_size = {-1, -1}, Point origin = {}) : W_num(W_num), H_num(H_num), whole_size(whole_size), origin(origin) {
init();
}
void init() { VRET; if(whole_size.real() < 0) whole_size = vis_internal::visualizer_campus_size;
cell_w = whole_size.real() / W_num; cell_h = whole_size.imag() / H_num;
cell_sz = {cell_w, cell_h}; }
double world_x(int col) const { return origin.real() + cell_w * col; }
double world_y(int row) const { return origin.imag() + cell_h * row; }
double world_top() const { return world_y(0); }
double world_bottom() const { return world_y(H_num); }
double world_left() const { return world_x(0); }
double world_right() const { return world_x(W_num); }
internal::Segment seg_horizontal(int y, int x, int len = 1) const {
return { Point{world_x(x), world_y(y)}, Point{world_x(x+len), world_y(y)} };
}
internal::Segment seg_horizontal(int y) const { return seg_horizontal(y, 0, W_num); }
internal::Segment seg_vertical(int x, int y, int len = 1) const {
return { Point{world_x(x), world_y(y)}, Point{world_x(x), world_y(y+len)} };
}
internal::Segment seg_vertical(int x) const { return seg_vertical(x, 0, H_num); }
internal::Box _internal_cell(int x, int y, int w, int h) const {
return { Point(world_x(x), world_y(y)), Point(cell_w*w, cell_h*h) };
}
internal::Box cell(int x, int y, int w, int h) const { return _internal_cell(x, y, h, w); }
internal::Box cell(int x, int y) const { return _internal_cell(x, y, 1, 1); }
internal::Box whole() const { return _internal_cell(0, 0, W_num, H_num); }
internal::Box operator()(int x, int y) const { return cell(x, y); }
internal::Box operator()() const { return whole(); }
};
void line(const Grid &grid, Vopt op = {}) { VRET;
for (int y = 0; y <= grid.H_num; ++y) { line(grid.seg_horizontal(y), op); }
for (int x = 0; x <= grid.W_num; ++x) { line(grid.seg_vertical(x), op); }
}
void rect(const Grid &grid, Vopt op = {}) { VRET; rect(grid(), op); op.v.fill.reset(); line(grid, op); }
} // namespace visualizer
// ----------------- 解法本体 -----------------
// ----------------- 解法本体 -----------------
#include <bits/stdc++.h>
using namespace std;
using namespace visualizer;
#define rep(i, n) for (int i = 0; i < (n); i++)
const int INF = 1e9;
int N, M;
vector<string> grid;
int pi, pj; // プレイヤー位置(初期は穴 'A' の位置)
struct Command {
int op; // 1:移動, 2:運ぶ, 3:転がす
char dir; // 'U','D','L','R'
};
vector<Command> ans;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
char dchar[4] = {'U', 'D', 'L', 'R'};
pair<int,int> holePos[26];
vector<vector<int>> computeHoleBFS(int type) {
vector<vector<int>> dist(N, vector<int>(N, INF));
queue<pair<int,int>> que;
int sr = holePos[type].first, sc = holePos[type].second;
dist[sr][sc] = 0;
que.push({sr, sc});
while(!que.empty()){
auto [r, c] = que.front(); que.pop();
rep(d, 4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
char cell = grid[nr][nc];
if(cell == '.' || cell == char('a' + type) || cell == char('A' + type)){
if(dist[nr][nc] > dist[r][c] + 1){
dist[nr][nc] = dist[r][c] + 1;
que.push({nr, nc});
}
}
}
}
return dist;
}
vector<vector<int>> bfs(int sr, int sc) {
vector<vector<int>> dist(N, vector<int>(N, INF));
queue<pair<int,int>> q;
dist[sr][sc] = 0;
q.push({sr, sc});
while(!q.empty()){
auto [r, c] = q.front(); q.pop();
rep(d,4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
if(dist[nr][nc] > dist[r][c] + 1){
dist[nr][nc] = dist[r][c] + 1;
q.push({nr, nc});
}
}
}
return dist;
}
vector<pair<int,int>> getPath(int sr, int sc, int tr, int tc) {
vector<vector<int>> dist(N, vector<int>(N, INF));
vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1,-1}));
queue<pair<int,int>> que;
dist[sr][sc] = 0;
que.push({sr, sc});
while(!que.empty()){
auto [r, c] = que.front(); que.pop();
if(r == tr && c == tc) break;
rep(d,4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
if(dist[nr][nc] > dist[r][c] + 1){
dist[nr][nc] = dist[r][c] + 1;
parent[nr][nc] = {r, c};
que.push({nr, nc});
}
}
}
vector<pair<int,int>> path;
if(dist[tr][tc] == INF) return path;
int r = tr, c = tc;
while(!(r == sr && c == sc)){
path.push_back({r, c});
auto p = parent[r][c];
r = p.first; c = p.second;
}
path.push_back({sr, sc});
reverse(path.begin(), path.end());
return path;
}
struct SimResult {
bool valid;
bool fell;
int score;
int new_r, new_c;
};
SimResult simulateCarry(int r, int c, int d_idx, const vector<vector<vector<int>>> &holeDist) {
SimResult res {false, false, 0, r, c};
char obj = grid[r][c];
if(!(obj >= 'a' && obj <= 'z')) return res;
int type = obj - 'a';
int nr = r + dx[d_idx], nc = c + dy[d_idx];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) return res;
char targetCell = grid[nr][nc];
if(targetCell != '.' && !(targetCell >= 'A' && targetCell <= 'Z')) return res;
char correctHole = char('A' + type);
int oldDist = holeDist[type][r][c];
if(oldDist == INF) return res;
if(targetCell >= 'A' && targetCell <= 'Z'){
if(targetCell == correctHole){
res.valid = true; res.fell = true; res.score = 100000;
return res;
}
return res;
}
int newDist = holeDist[type][nr][nc];
if(newDist < oldDist){
res.valid = true; res.fell = false;
// int min_dis_improvement = (20 - min(abs(nr - holePos[type].first), abs(nc - holePos[type].second)));
int old_min_dis = min(abs(r - holePos[type].first), abs(c - holePos[type].second));
int new_min_dis = min(abs(nr - holePos[type].first), abs(nc - holePos[type].second));
int min_dis_improvement = max(0, old_min_dis - new_min_dis) * 1;
int improvement = oldDist - newDist;
res.score = improvement * improvement * 10 + min_dis_improvement;
res.new_r = nr; res.new_c = nc;
}
return res;
}
SimResult simulateRoll(int r, int c, int d_idx, const vector<vector<vector<int>>> &holeDist) {
SimResult res {false, false, 0, r, c};
char obj = grid[r][c];
if (!(obj >= 'a' && obj <= 'z')) return res;
int type = obj - 'a';
char correctHole = char('A' + type);
int oldDist = holeDist[type][r][c];
if (oldDist == INF) return res;
int cur_r = r, cur_c = c;
while (true) {
int nr = cur_r + dx[d_idx], nc = cur_c + dy[d_idx];
if (nr < 0 || nr >= N || nc < 0 || nc >= N) break;
char cell = grid[nr][nc];
// 新規チェック:もし cell が鉱石なら、その先も確認する
if (cell >= 'a' && cell <= 'z') {
int ar = nr + dx[d_idx], ac = nc + dy[d_idx];
if (ar >= 0 && ar < N && ac >= 0 && ac < N) {
char cell2 = grid[ar][ac];
if (cell2 != '.') { // 空きマスでなければペナルティ
res.valid = true;
res.fell = false;
// res.score = -5000;
// return res;
}
}
break; // 衝突したのでループ終了
}
if (cell >= 'A' && cell <= 'Z') {
// 穴にぶつかった場合:正しい穴なら落下(消失)として評価
if (cell == correctHole) {
res.valid = true;
res.fell = true;
res.score = 100000;
}
return res;
}
if (cell == '@') break;
cur_r = nr; cur_c = nc;
}
int newDist = holeDist[type][cur_r][cur_c];
if (newDist < oldDist) {
res.valid = true;
res.fell = false;
int improvement = oldDist - newDist;
res.score += improvement * improvement * 10;
res.new_r = cur_r; res.new_c = cur_c;
}
return res;
}
void performMove(int op, int d_idx) {
Command cmd; cmd.op = op; cmd.dir = dchar[d_idx];
ans.push_back(cmd);
if(op == 1) {
pi += dx[d_idx]; pj += dy[d_idx];
} else if(op == 2) {
int nr = pi + dx[d_idx], nc = pj + dy[d_idx];
char obj = grid[pi][pj];
grid[pi][pj] = '.';
if(grid[nr][nc] >= 'A' && grid[nr][nc] <= 'Z'){
// 穴なら落下(除去)
} else {
grid[nr][nc] = obj;
}
pi = nr; pj = nc;
} else if(op == 3) {
int r = pi, c = pj;
char obj = grid[r][c];
grid[r][c] = '.';
int cur_r = r, cur_c = c;
while(true) {
int nr = cur_r + dx[d_idx], nc = cur_c + dy[d_idx];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) break;
char cell = grid[nr][nc];
if(cell >= 'A' && cell <= 'Z'){
if(obj == '@') {
// 岩の場合は、穴にぶつかったら必ず落下(消失)
return;
} else {
// 鉱石の場合は、正しい穴なら落下
if(cell == char('A' + (obj - 'a'))){
return;
}
break;
}
}
if(cell == '@' || (cell >= 'a' && cell <= 'z')) break;
cur_r = nr; cur_c = nc;
}
grid[cur_r][cur_c] = obj;
}
}
// drawState: Grid を用いて盤面を描画する(色設定は以前の例通り)
void drawState(const Grid &G) {
for (int i = 0; i < N; i++){
for (int j = 0; j < N; j++){
char cell = grid[i][j];
if(cell == '@'){
rect(G(j, i), "gray");
} else if(cell >= 'a' && cell <= 'z'){
string col;
int type = cell - 'a';
if(type == 0) col = "#ff6666"; // 鉱石 a: 赤系
else if(type == 1) col = "#66ff66"; // 鉱石 b: 緑系
else if(type == 2) col = "#6666ff"; // 鉱石 c: 青系
else col = "#cccccc";
circle(G(j, i), min(G.cell_sz.real(), G.cell_sz.imag())/4, Vopt(col).stroke(col, 1));
} else if(cell >= 'A' && cell <= 'Z'){
string col;
int type = cell - 'A';
if(type == 0) col = "#ff0000"; // 穴 A: 赤
else if(type == 1) col = "#00ff00"; // 穴 B: 緑
else if(type == 2) col = "#0000ff"; // 穴 C: 青
else col = "#999999";
circle(G(j, i), min(G.cell_sz.real(), G.cell_sz.imag())/3, Vopt(col).stroke(col, 1));
}
}
}
circle(G(pj, pi), min(G.cell_sz.real(), G.cell_sz.imag())/3, Vopt("", "black", 2));
}
void printGrid() {
rep(i, N) {
rep(j, N) {
cerr << grid[i][j];
}
cerr << endl;
}
}
// ----- 新規追加:鉱石が存在するエリアを DFS で計算する -----
set<pair<int,int>> getMineralArea() {
set<pair<int,int>> area;
vector<vector<bool>> visited(N, vector<bool>(N, false));
rep(i, N) {
rep(j, N) {
// 岩は含まない
if(grid[i][j] == '@' || visited[i][j]) continue;
// DFS で連結領域を求める
vector<pair<int,int>> comp;
bool containsMineral = false;
stack<pair<int,int>> st;
st.push({i,j});
visited[i][j] = true;
while(!st.empty()){
auto [r, c] = st.top();
st.pop();
comp.push_back({r, c});
if(grid[r][c] >= 'a' && grid[r][c] <= 'z') containsMineral = true;
rep(d,4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
if(grid[nr][nc] == '@') continue;
if(!visited[nr][nc]){
visited[nr][nc] = true;
st.push({nr, nc});
}
}
}
if(containsMineral) {
for(auto &p : comp) area.insert(p);
}
}
}
return area;
}
// DigCandidate 用構造体
struct DigCandidate {
int digs;
int distFromHole;
pair<int,int> cell;
int dir; // 0:U,1:D,2:L,3:R
};
// evaluateDigCandidate: 指定の境界セル cell と方向 d に対し、
// 隣接する岩群を除去した先のセルが、あらかじめ計算された mineralArea に含まれているかを判定する。
optional<DigCandidate> evaluateDigCandidate(const set<pair<int,int>> &mineralArea,
const vector<vector<int>> &curDist, pair<int,int> cell, int d) {
int r = cell.first, c = cell.second;
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) return nullopt;
if(grid[nr][nc] != '@') return nullopt;
int digs = 0;
// 岩が連続する部分を数える
while(nr >= 0 && nr < N && nc >= 0 && nc < N && grid[nr][nc] == '@') {
digs++;
nr += dx[d]; nc += dy[d];
}
if(nr < 0 || nr >= N || nc < 0 || nc >= N) return nullopt;
// ここで、候補先は (nr, nc) ですが、実際の掘削操作では、boundary cell から
// d の反対方向 (oppDir) に digs 回ロールして岩を除去する必要がある。
int oppDir = (d == 0 ? 1 : (d == 1 ? 0 : (d == 2 ? 3 : 2)));
// 仮想盤面 tempGrid において、候補の岩群を除去するシミュレーション
auto tempGrid = grid; // grid のコピー
// 掘削すべき岩は、boundary cell の隣(cell + d 方向)から digs 個
int rr = r + dx[d], cc = c + dy[d];
for (int k = 0; k < digs; k++) {
if(rr < 0 || rr >= N || cc < 0 || cc >= N) break;
tempGrid[rr][cc] = '.'; // 岩を除去
rr += dx[d]; cc += dy[d];
}
// さらに、候補として実際に反対方向に roll するシミュレーションを行う
// すなわち、boundary cell から oppDir に1歩移動(実際の掘削操作のセットの前段)をシミュレーション
int test_r = r + dx[oppDir], test_c = c + dy[oppDir];
if(test_r < 0 || test_r >= N || test_c < 0 || test_c >= N) return nullopt;
// tempGrid の該当位置を空にしておく(もし岩であれば、roll により除去されると想定)
tempGrid[test_r][test_c] = '.';
// 仮想盤面 tempGrid を用いて、穴 'A' からの BFS を行う局所版 computeHoleBFS
auto computeHoleBFS_temp = [&tempGrid](int type) -> vector<vector<int>> {
vector<vector<int>> dist(N, vector<int>(N, INF));
queue<pair<int,int>> que;
int sr = holePos[type].first, sc = holePos[type].second;
dist[sr][sc] = 0;
que.push({sr, sc});
while(!que.empty()){
auto [r, c] = que.front(); que.pop();
rep(d,4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
char cell = tempGrid[nr][nc];
if(cell == '.' || cell == char('a' + type) || cell == char('A' + type)){
if(dist[nr][nc] > dist[r][c] + 1){
dist[nr][nc] = dist[r][c] + 1;
que.push({nr, nc});
}
}
}
}
return dist;
};
// M=1 の場合、type は 0 とする
auto newHoleDist = computeHoleBFS_temp(0);
// 掘削後、穴 'A' の領域に、mineralArea のどれかのセルが含まれていれば接続成功
bool connected = false;
for(auto &p : mineralArea) {
int r0 = p.first, c0 = p.second;
if(newHoleDist[r0][c0] < INF) { connected = true; break; }
}
if(!connected) return nullopt;
DigCandidate cand {digs, curDist[r][c], {r, c}, d};
return cand;
}
// ----- メインループ -----
// まず、連結エリア内に鉱石がある場合は従来の回収を行い、なければ、連結エリアの境界から掘削候補を評価
void solve() {
cin >> N >> M;
visualizer_helper visualizer_helper(Point{N*10.0, N*10.0});
grid.resize(N);
rep(i, N) {
cin >> grid[i];
}
rep(i, N) {
rep(j, N) {
char c = grid[i][j];
if(c >= 'A' && c <= 'Z'){
int type = c - 'A';
holePos[type] = {i, j};
if(c == 'A'){
pi = i; pj = j;
}
}
}
}
vector<vector<vector<int>>> holeDist;
holeDist.resize(M);
rep(t, M) {
holeDist[t] = computeHoleBFS(t);
}
Grid G(N);
rect(G, "#fff");
line(G, Vopt("#bbb", 0.2));
vtime(0);
drawState(G);
int moves = 0;
while(moves < 10000) {
// cerr << "moves: " << moves << endl;
bool mineralExists = false;
rep(i, N) {
rep(j, N) {
if(grid[i][j] >= 'a' && grid[i][j] <= 'z'){
mineralExists = true;
break;
}
}
if(mineralExists) break;
}
if(!mineralExists) {
cerr << "No mineral found" << endl;
break;
}
// 現在地からの距離を計算
vector<vector<int>> curDist = bfs(pi, pj);
// まず、連結エリア(穴から到達可能なエリア)内に鉱石があるかチェック
set<pair<int,int>> connectedRegion;
{
// ここでは、getConnectedRegion() を既存の方法で計算(省略可)
// ※既存コード例では region を hole からの BFS で求める
queue<pair<int,int>> q;
vector<vector<bool>> vis(N, vector<bool>(N, false));
int start_r = holePos[0].first, start_c = holePos[0].second;
q.push({start_r, start_c}); // TODO
vis[start_r][start_c] = true;
while(!q.empty()){
auto [r, c] = q.front(); q.pop();
connectedRegion.insert({r, c});
rep(d,4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
if(!vis[nr][nc] && grid[nr][nc] != '@'){
vis[nr][nc] = true;
q.push({nr, nc});
}
}
}
}
bool hasMineralInRegion = false;
for(auto &p : connectedRegion) {
int r = p.first, c = p.second;
if(grid[r][c] >= 'a' && grid[r][c] <= 'z'){
hasMineralInRegion = true;
break;
}
}
// printGrid();
// cerr << "hasMineralInRegion: " << hasMineralInRegion << endl;
if(hasMineralInRegion) {
// 通常の回収フェーズ(従来の評価:評価値 = (穴までの距離) - max(0, (現在地からの距離-1))*10000)
int candidate_target_r = -1, candidate_target_c = -1, candidate_targetType = -1;
int candidate_bestVal = -1000000000;
SimResult candidate_bestOpRes;
bool candidateFound = false;
rep(i, N) {
rep(j, N) {
if(grid[i][j] >= 'a' && grid[i][j] <= 'z'){
int type = grid[i][j] - 'a';
int d_h = holeDist[type][i][j];
if(d_h == INF) continue;
int penalty = max(0, curDist[i][j] - 1) * 10000;
if(abs(holePos[type].first - i) == 1 || abs(holePos[type].second - j) == 1){
penalty += 100;
}
int eval = d_h - penalty;
SimResult bestOpForCell {false, false, 0, i, j};
bool validFoundForCell = false;
rep(dir,4) {
int score_offset = 0;
SimResult resCarry = simulateCarry(i, j, dir, holeDist);
SimResult resRoll = simulateRoll(i, j, dir, holeDist);
resCarry.score += score_offset;
resRoll.score += score_offset;
if(resCarry.valid && resCarry.score > bestOpForCell.score){
bestOpForCell = resCarry;
validFoundForCell = true;
}
if(resRoll.valid && resRoll.score > bestOpForCell.score){
bestOpForCell = resRoll;
validFoundForCell = true;
}
}
if(validFoundForCell && eval > candidate_bestVal) {
candidate_bestVal = eval;
candidate_target_r = i;
candidate_target_c = j;
candidate_targetType = type;
candidate_bestOpRes = bestOpForCell;
candidateFound = true;
}
}
}
}
if(!candidateFound) break;
vector<pair<int,int>> path = getPath(pi, pj, candidate_target_r, candidate_target_c);
if(path.empty()) break;
for (int i = 1; i < (int)path.size() && moves < 10000; i++){
int cr = path[i-1].first, cc = path[i-1].second;
int nr = path[i].first, nc = path[i].second;
int d_idx = -1;
rep(d,4) {
if(cr + dx[d] == nr && cc + dy[d] == nc){
d_idx = d;
break;
}
}
performMove(1, d_idx);
moves++;
vtime(moves);
drawState(G);
}
int chosenOp = -1, chosenDir = -1;
if(candidate_bestOpRes.valid){
int bestScore = candidate_bestOpRes.score;
rep(d,4) {
SimResult r1 = simulateCarry(pi, pj, d, holeDist);
if(r1.valid && r1.score == bestScore) { chosenOp = 2; chosenDir = d; break; }
SimResult r2 = simulateRoll(pi, pj, d, holeDist);
if(r2.valid && r2.score == bestScore) { chosenOp = 3; chosenDir = d; break; }
}
}
if(chosenOp == -1) break;
performMove(chosenOp, chosenDir);
moves++;
vtime(moves);
drawState(G);
if (M > 1) rep(t, M) {
holeDist[t] = computeHoleBFS(t);
}
} else {
// 連結エリア内に鉱石が無い場合:まず、非岩セル同士で連結しているうち、鉱石が存在するエリアを DFS で計算する
set<pair<int,int>> mineralArea = getMineralArea();
// 連結エリア(hole から到達可能なエリア)の境界(隣接して岩があるセル)を抽出
vector<pair<int,int>> boundaries;
for(auto p : connectedRegion) {
int r = p.first, c = p.second;
rep(d,4) {
int nr = r + dx[d], nc = c + dy[d];
if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
if(grid[nr][nc] == '@'){
boundaries.push_back({r, c});
break;
}
}
}
// 各境界セルについて、各方向の掘削候補を評価
optional<DigCandidate> bestCand;
for(auto cell : boundaries) {
rep(d,4) {
auto cand = evaluateDigCandidate(mineralArea, curDist, cell, d);
if(cand) {
if(!bestCand.has_value() || cand->digs < bestCand->digs ||
(cand->digs == bestCand->digs && cand->distFromHole < bestCand->distFromHole))
{
bestCand = cand;
}
}
}
}
if(!bestCand.has_value()) break;
vector<pair<int,int>> path = getPath(pi, pj, bestCand->cell.first, bestCand->cell.second);
if(path.empty()) break;
for (int i = 1; i < (int)path.size() && moves < 10000; i++){
int cr = path[i-1].first, cc = path[i-1].second;
int nr = path[i].first, nc = path[i].second;
int d_idx = -1;
rep(d,4) {
if(cr + dx[d] == nr && cc + dy[d] == nc){
d_idx = d;
break;
}
}
performMove(1, d_idx);
moves++;
vtime(moves);
drawState(G);
}
// cerr << "bestCand.cell: " << bestCand->cell.first << "," << bestCand->cell.second << " " << bestCand->digs << " " << bestCand->dir << "\n";
// 掘削操作:候補で決定した方向へ、候補の digs 回だけ roll 操作を実行
int oppDir = (bestCand->dir == 0 ? 1 : (bestCand->dir == 1 ? 0 : (bestCand->dir == 2 ? 3 : 2)));
rep(i, bestCand->digs) {
performMove(1, bestCand->dir);
moves++;
vtime(moves);
drawState(G);
performMove(3, oppDir);
moves++;
vtime(moves);
drawState(G);
}
// 掘削後、holeDist を再計算
rep(t, M) {
holeDist[t] = computeHoleBFS(t);
}
// cerr << "掘削ed: "<< endl;
}
}
for(auto &cmd : ans) {
cout << cmd.op << " " << cmd.dir << "\n";
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
Submission Info
Submission Time |
|
Task |
A - Ore Rolling (A) |
User |
TumoiYorozu |
Language |
C++ 20 (gcc 12.2) |
Score |
769212572 |
Code Size |
42540 Byte |
Status |
AC |
Exec Time |
14 ms |
Memory |
3696 KiB |
Compile Error
Main.cpp: In function ‘void solve()’:
Main.cpp:914:67: warning: variable ‘candidate_targetType’ set but not used [-Wunused-but-set-variable]
914 | int candidate_target_r = -1, candidate_target_c = -1, candidate_targetType = -1;
| ^~~~~~~~~~~~~~~~~~~~
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {const char*, const char*}]’:
Main.cpp:192:20: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {const char*, float}]’:
Main.cpp:195:20: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {const char*}]’:
Main.cpp:204:32: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {}]’:
Main.cpp:205:28: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {short int}]’:
Main.cpp:210:24: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {double, double, float}]’:
Main.cpp:253:10: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#2’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {double, double, double, double}]’:
Main.cpp:267:10: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#2’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#3’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {double, double, double, double, float, double, double}]’:
Main.cpp:284:10: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#2’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#3’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#4’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#5’ [-Wunused-parameter]
Main.cpp:169:36: warning: unused parameter ‘args#6’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {double, double}]’:
Main.cpp:292:27: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {int}]’:
Main.cpp:339:31: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp: In instantiation of ‘void visualizer::print(const char*, Args ...) [with Args = {int, int}]’:
Main.cpp:340:26: required from here
Main.cpp:169:24: warning: unused parameter ‘format’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~~~~~~~~~^~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#0’ [-Wunused-parameter]
169 | void print(const char* format, Args... args) { return; }
| ~~~~^~~~~~~~
Main.cpp:169:36: warning: unused parameter ‘args#1’ [-Wunused-parameter]
Main.cpp: In instantiation of ‘visualizer::visualizer_helper::visualizer_helper(Args ...) [with Args = {std::complex<double>}]’:
Main.cpp:824:62: required from here
Main.cpp:167:77: warning: unused parameter ‘args#0’ [-Wunused-parameter]
167 | struct visualizer_helper { template<typename... Args> visualizer_helper(Args... args) {} };
| ~~~~^~~~~~~~
Main.cpp:985:33: warning: ‘candidate_bestOpRes.SimResult::score’ may be used uninitialized [-Wmaybe-uninitialized]
985 | if(r2.valid && r2.score == bestScore) { chosenOp = 3; chosenDir = d; break; }
| ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:916:23: note: ‘candidate_bestOpRes.SimResult::score’ was declared here
916 | SimResult candidate_bestOpRes;
| ^~~~~~~~~~~~~~~~~~~
Judge Result
Set Name |
test_ALL |
Score / Max Score |
769212572 / 1500000000 |
Status |
|
Set Name |
Test Cases |
test_ALL |
test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt |
Case Name |
Status |
Exec Time |
Memory |
test_0000.txt |
AC |
8 ms |
3544 KiB |
test_0001.txt |
AC |
7 ms |
3696 KiB |
test_0002.txt |
AC |
10 ms |
3572 KiB |
test_0003.txt |
AC |
9 ms |
3556 KiB |
test_0004.txt |
AC |
7 ms |
3492 KiB |
test_0005.txt |
AC |
8 ms |
3544 KiB |
test_0006.txt |
AC |
7 ms |
3480 KiB |
test_0007.txt |
AC |
9 ms |
3496 KiB |
test_0008.txt |
AC |
8 ms |
3548 KiB |
test_0009.txt |
AC |
6 ms |
3492 KiB |
test_0010.txt |
AC |
7 ms |
3564 KiB |
test_0011.txt |
AC |
7 ms |
3508 KiB |
test_0012.txt |
AC |
7 ms |
3620 KiB |
test_0013.txt |
AC |
8 ms |
3484 KiB |
test_0014.txt |
AC |
6 ms |
3556 KiB |
test_0015.txt |
AC |
6 ms |
3524 KiB |
test_0016.txt |
AC |
9 ms |
3692 KiB |
test_0017.txt |
AC |
7 ms |
3516 KiB |
test_0018.txt |
AC |
7 ms |
3560 KiB |
test_0019.txt |
AC |
7 ms |
3568 KiB |
test_0020.txt |
AC |
9 ms |
3568 KiB |
test_0021.txt |
AC |
6 ms |
3520 KiB |
test_0022.txt |
AC |
6 ms |
3540 KiB |
test_0023.txt |
AC |
7 ms |
3620 KiB |
test_0024.txt |
AC |
6 ms |
3544 KiB |
test_0025.txt |
AC |
9 ms |
3488 KiB |
test_0026.txt |
AC |
7 ms |
3476 KiB |
test_0027.txt |
AC |
8 ms |
3472 KiB |
test_0028.txt |
AC |
9 ms |
3496 KiB |
test_0029.txt |
AC |
7 ms |
3560 KiB |
test_0030.txt |
AC |
8 ms |
3540 KiB |
test_0031.txt |
AC |
7 ms |
3568 KiB |
test_0032.txt |
AC |
8 ms |
3456 KiB |
test_0033.txt |
AC |
9 ms |
3688 KiB |
test_0034.txt |
AC |
7 ms |
3556 KiB |
test_0035.txt |
AC |
7 ms |
3556 KiB |
test_0036.txt |
AC |
7 ms |
3604 KiB |
test_0037.txt |
AC |
7 ms |
3560 KiB |
test_0038.txt |
AC |
7 ms |
3480 KiB |
test_0039.txt |
AC |
7 ms |
3568 KiB |
test_0040.txt |
AC |
7 ms |
3568 KiB |
test_0041.txt |
AC |
8 ms |
3620 KiB |
test_0042.txt |
AC |
8 ms |
3552 KiB |
test_0043.txt |
AC |
6 ms |
3568 KiB |
test_0044.txt |
AC |
6 ms |
3568 KiB |
test_0045.txt |
AC |
8 ms |
3504 KiB |
test_0046.txt |
AC |
6 ms |
3444 KiB |
test_0047.txt |
AC |
7 ms |
3620 KiB |
test_0048.txt |
AC |
7 ms |
3512 KiB |
test_0049.txt |
AC |
8 ms |
3500 KiB |
test_0050.txt |
AC |
7 ms |
3572 KiB |
test_0051.txt |
AC |
9 ms |
3508 KiB |
test_0052.txt |
AC |
6 ms |
3548 KiB |
test_0053.txt |
AC |
9 ms |
3564 KiB |
test_0054.txt |
AC |
7 ms |
3468 KiB |
test_0055.txt |
AC |
8 ms |
3492 KiB |
test_0056.txt |
AC |
8 ms |
3532 KiB |
test_0057.txt |
AC |
6 ms |
3540 KiB |
test_0058.txt |
AC |
7 ms |
3548 KiB |
test_0059.txt |
AC |
9 ms |
3576 KiB |
test_0060.txt |
AC |
6 ms |
3488 KiB |
test_0061.txt |
AC |
7 ms |
3564 KiB |
test_0062.txt |
AC |
7 ms |
3480 KiB |
test_0063.txt |
AC |
9 ms |
3496 KiB |
test_0064.txt |
AC |
7 ms |
3572 KiB |
test_0065.txt |
AC |
8 ms |
3568 KiB |
test_0066.txt |
AC |
7 ms |
3600 KiB |
test_0067.txt |
AC |
7 ms |
3560 KiB |
test_0068.txt |
AC |
8 ms |
3560 KiB |
test_0069.txt |
AC |
6 ms |
3596 KiB |
test_0070.txt |
AC |
9 ms |
3568 KiB |
test_0071.txt |
AC |
6 ms |
3556 KiB |
test_0072.txt |
AC |
8 ms |
3504 KiB |
test_0073.txt |
AC |
8 ms |
3496 KiB |
test_0074.txt |
AC |
8 ms |
3524 KiB |
test_0075.txt |
AC |
9 ms |
3620 KiB |
test_0076.txt |
AC |
9 ms |
3532 KiB |
test_0077.txt |
AC |
8 ms |
3604 KiB |
test_0078.txt |
AC |
8 ms |
3508 KiB |
test_0079.txt |
AC |
6 ms |
3568 KiB |
test_0080.txt |
AC |
7 ms |
3692 KiB |
test_0081.txt |
AC |
9 ms |
3512 KiB |
test_0082.txt |
AC |
8 ms |
3612 KiB |
test_0083.txt |
AC |
6 ms |
3480 KiB |
test_0084.txt |
AC |
8 ms |
3620 KiB |
test_0085.txt |
AC |
7 ms |
3564 KiB |
test_0086.txt |
AC |
7 ms |
3388 KiB |
test_0087.txt |
AC |
6 ms |
3556 KiB |
test_0088.txt |
AC |
6 ms |
3568 KiB |
test_0089.txt |
AC |
6 ms |
3564 KiB |
test_0090.txt |
AC |
7 ms |
3560 KiB |
test_0091.txt |
AC |
8 ms |
3556 KiB |
test_0092.txt |
AC |
7 ms |
3696 KiB |
test_0093.txt |
AC |
7 ms |
3484 KiB |
test_0094.txt |
AC |
7 ms |
3684 KiB |
test_0095.txt |
AC |
10 ms |
3552 KiB |
test_0096.txt |
AC |
8 ms |
3572 KiB |
test_0097.txt |
AC |
7 ms |
3560 KiB |
test_0098.txt |
AC |
6 ms |
3556 KiB |
test_0099.txt |
AC |
10 ms |
3548 KiB |
test_0100.txt |
AC |
9 ms |
3692 KiB |
test_0101.txt |
AC |
7 ms |
3540 KiB |
test_0102.txt |
AC |
8 ms |
3616 KiB |
test_0103.txt |
AC |
8 ms |
3552 KiB |
test_0104.txt |
AC |
8 ms |
3456 KiB |
test_0105.txt |
AC |
7 ms |
3500 KiB |
test_0106.txt |
AC |
14 ms |
3580 KiB |
test_0107.txt |
AC |
8 ms |
3480 KiB |
test_0108.txt |
AC |
8 ms |
3472 KiB |
test_0109.txt |
AC |
7 ms |
3508 KiB |
test_0110.txt |
AC |
7 ms |
3484 KiB |
test_0111.txt |
AC |
8 ms |
3468 KiB |
test_0112.txt |
AC |
8 ms |
3552 KiB |
test_0113.txt |
AC |
10 ms |
3504 KiB |
test_0114.txt |
AC |
6 ms |
3552 KiB |
test_0115.txt |
AC |
8 ms |
3544 KiB |
test_0116.txt |
AC |
6 ms |
3680 KiB |
test_0117.txt |
AC |
6 ms |
3504 KiB |
test_0118.txt |
AC |
6 ms |
3564 KiB |
test_0119.txt |
AC |
8 ms |
3552 KiB |
test_0120.txt |
AC |
8 ms |
3696 KiB |
test_0121.txt |
AC |
7 ms |
3500 KiB |
test_0122.txt |
AC |
8 ms |
3504 KiB |
test_0123.txt |
AC |
6 ms |
3460 KiB |
test_0124.txt |
AC |
7 ms |
3564 KiB |
test_0125.txt |
AC |
6 ms |
3604 KiB |
test_0126.txt |
AC |
6 ms |
3596 KiB |
test_0127.txt |
AC |
9 ms |
3564 KiB |
test_0128.txt |
AC |
7 ms |
3476 KiB |
test_0129.txt |
AC |
7 ms |
3692 KiB |
test_0130.txt |
AC |
7 ms |
3564 KiB |
test_0131.txt |
AC |
7 ms |
3616 KiB |
test_0132.txt |
AC |
9 ms |
3492 KiB |
test_0133.txt |
AC |
6 ms |
3528 KiB |
test_0134.txt |
AC |
7 ms |
3412 KiB |
test_0135.txt |
AC |
6 ms |
3464 KiB |
test_0136.txt |
AC |
7 ms |
3504 KiB |
test_0137.txt |
AC |
6 ms |
3516 KiB |
test_0138.txt |
AC |
9 ms |
3512 KiB |
test_0139.txt |
AC |
6 ms |
3492 KiB |
test_0140.txt |
AC |
8 ms |
3608 KiB |
test_0141.txt |
AC |
8 ms |
3560 KiB |
test_0142.txt |
AC |
5 ms |
3688 KiB |
test_0143.txt |
AC |
8 ms |
3612 KiB |
test_0144.txt |
AC |
7 ms |
3412 KiB |
test_0145.txt |
AC |
6 ms |
3552 KiB |
test_0146.txt |
AC |
9 ms |
3560 KiB |
test_0147.txt |
AC |
7 ms |
3608 KiB |
test_0148.txt |
AC |
6 ms |
3604 KiB |
test_0149.txt |
AC |
9 ms |
3548 KiB |