結果
問題 | No.5016 Worst Mayor |
ユーザー | yunix |
提出日時 | 2023-04-29 14:58:06 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 92 ms / 2,000 ms |
コード長 | 10,096 bytes |
コンパイル時間 | 1,939 ms |
コンパイル使用メモリ | 145,100 KB |
実行使用メモリ | 24,276 KB |
スコア | 12,633,778,820 |
平均クエリ数 | 400.00 |
最終ジャッジ日時 | 2023-04-29 14:58:17 |
合計ジャッジ時間 | 10,003 ms |
ジャッジサーバーID (参考情報) |
judge14 / judge15 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 92 ms
23,532 KB |
testcase_01 | AC | 86 ms
23,256 KB |
testcase_02 | AC | 87 ms
24,000 KB |
testcase_03 | AC | 87 ms
24,024 KB |
testcase_04 | AC | 86 ms
23,976 KB |
testcase_05 | AC | 90 ms
24,144 KB |
testcase_06 | AC | 88 ms
23,664 KB |
testcase_07 | AC | 86 ms
24,144 KB |
testcase_08 | AC | 86 ms
23,232 KB |
testcase_09 | AC | 88 ms
23,952 KB |
testcase_10 | AC | 87 ms
24,144 KB |
testcase_11 | AC | 89 ms
23,364 KB |
testcase_12 | AC | 86 ms
23,412 KB |
testcase_13 | AC | 87 ms
23,940 KB |
testcase_14 | AC | 85 ms
24,156 KB |
testcase_15 | AC | 86 ms
23,436 KB |
testcase_16 | AC | 87 ms
24,276 KB |
testcase_17 | AC | 87 ms
23,412 KB |
testcase_18 | AC | 86 ms
23,256 KB |
testcase_19 | AC | 87 ms
23,820 KB |
testcase_20 | AC | 87 ms
23,376 KB |
testcase_21 | AC | 87 ms
23,628 KB |
testcase_22 | AC | 87 ms
23,400 KB |
testcase_23 | AC | 87 ms
23,520 KB |
testcase_24 | AC | 87 ms
23,424 KB |
testcase_25 | AC | 88 ms
23,640 KB |
testcase_26 | AC | 84 ms
24,012 KB |
testcase_27 | AC | 86 ms
23,664 KB |
testcase_28 | AC | 87 ms
23,844 KB |
testcase_29 | AC | 86 ms
23,256 KB |
testcase_30 | AC | 87 ms
23,400 KB |
testcase_31 | AC | 87 ms
23,856 KB |
testcase_32 | AC | 88 ms
23,808 KB |
testcase_33 | AC | 87 ms
23,412 KB |
testcase_34 | AC | 90 ms
23,832 KB |
testcase_35 | AC | 88 ms
24,168 KB |
testcase_36 | AC | 86 ms
23,256 KB |
testcase_37 | AC | 86 ms
23,856 KB |
testcase_38 | AC | 84 ms
24,000 KB |
testcase_39 | AC | 86 ms
23,532 KB |
testcase_40 | AC | 87 ms
24,156 KB |
testcase_41 | AC | 85 ms
23,424 KB |
testcase_42 | AC | 86 ms
23,244 KB |
testcase_43 | AC | 87 ms
23,664 KB |
testcase_44 | AC | 87 ms
23,256 KB |
testcase_45 | AC | 87 ms
23,604 KB |
testcase_46 | AC | 87 ms
23,232 KB |
testcase_47 | AC | 87 ms
23,520 KB |
testcase_48 | AC | 86 ms
23,928 KB |
testcase_49 | AC | 87 ms
23,412 KB |
ソースコード
#include <iostream> #include <string> #include <vector> #include <tuple> #include <chrono> #include <algorithm> #include <random> #include <map> #include <set> #include <queue> #include <random> #include <chrono> #include <cmath> #include <climits> #include <bitset> #include <time.h> using namespace std; using Ps = pair<short, short>; using vec_int = vector<int>; using P = pair<int, int>; using P2 = pair<P, P>; using P3 = pair<float, int>; // using T = tuple<int, int, int>; using Td = tuple<double, int, int, int>; using T2 = tuple<float, int, int>; using T3 = tuple<float, int, int, int, int>; using T4 = tuple<int, int, int, int>; using T5 = tuple<int, int, int, int, int>; using TT = tuple<int, int, int>; using ll = long long; using uc = unsigned char; #define rep(i, n) for (int i = 0; i < (int)(n); i++) int N, T; vec_int A, B, C, D; // #pragma GCC optimize("Ofast") std::mt19937 mt{12345}; int RAND_ARR_LEN = 100000; int RAND_RANGE = 1000000000; float TIME_LIMIT = 2000; float INV_TIME_LIMIT = 1. / 1000.; const int JOB_MAX_LEN = 1003; std::uniform_int_distribution<int> dist(1, RAND_RANGE); int WAITING_TASK = 1001; void remove_val_and_pop_from_last(vec_int &A, int val) { for (int i = 0; i < A.size(); i++) { if (A.at(i) == val) { A.at(i) = A.at(A.size() - 1); A.pop_back(); return; } } throw runtime_error("trying to remove non-existing value"); } class Rand { private: int count = 0; vec_int rand_arr; public: Rand(){ rep(i, RAND_ARR_LEN){ rand_arr.push_back(dist(mt)); } } ; int get(); int get_rand(int from, int to); float get_float(); } ; int Rand::get() { int num = rand_arr.at(count); count += 1; count %= RAND_ARR_LEN; return num; } int Rand::get_rand(int from, int to) { int diff = to - from; int num = get() % diff; return num + from; } float Rand::get_float() { // 0~1の間の一様乱数 return (float)get() / (float)RAND_RANGE; } Rand ro; class PseudoSet { private: vec_int index_arr; public: vec_int data; PseudoSet(){}; PseudoSet(int value_range) { index_arr = vec_int(value_range, -1); } bool count(int value); void insert(int value); void erase(int value); vec_int get_data() { return data; }; int size() { return data.size(); }; int get_random() { return data.at(ro.get_rand(0, size())); }; }; bool PseudoSet::count(int value) { return index_arr[value] != -1; } void PseudoSet::insert(int value) { if (count(value)) return; index_arr[value] = data.size(); data.push_back(value); } void PseudoSet::erase(int value) { if (!count(value)) { // throw runtime_error("no existing value:"+to_string(value)); return; } int tail_value = data[data.size() - 1]; if (value == tail_value) { data.pop_back(); index_arr[value] = -1; } else { index_arr[tail_value] = index_arr[value]; index_arr[value] = -1; data[index_arr[tail_value]] = tail_value; data.pop_back(); } } float get_time(bool init) { static std::chrono::system_clock::time_point start; if (init) { start = std::chrono::system_clock::now(); } std::chrono::system_clock::time_point end = std::chrono::system_clock::now(); return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); // 処理に要した時間をミリ秒に変換 } double current_tmp(double current_time, double T0, double T1) { return T1 + (T0 - T1) * (TIME_LIMIT * 0.92 - current_time) / (TIME_LIMIT * 0.92); // double start_time = TIME_LIMIT * 0.6; // double x = (current_time - start_time) / (TIME_LIMIT * 0.32); // return pow(T1, 1 - x) + (T0, x); } bool is_valid_transition(int diff, double current_time, double T0, float T1) { float t = current_tmp(current_time, T0, T1); float rand = ro.get_float(); // diffが正だったら常にアクセぷと return rand < exp(((float)diff) / t); } class CityMap { private: int count_highway(int num); double cost_between(int x, int y, int z, int w); public: vector<vector<double>> horizontal_cost; vector<vector<double>> vertical_cost; CityMap(); void upgrade_road(int x, int y, int z, int w); int calculate_income(); }; CityMap::CityMap() { horizontal_cost = vector<vector<double>>(14, vector<double>(13, 1)); vertical_cost = vector<vector<double>>(14, vector<double>(13, 1)); } void CityMap::upgrade_road(int x, int y, int z, int w) { if (x == z) { // この時には横方向の道 int ymin = min(y, w); horizontal_cost.at(x - 1).at(ymin - 1) = 0.223; } else { int xmin = min(x, z); vertical_cost.at(y - 1).at(xmin - 1) = 0.223; } } double CityMap::cost_between(int x, int y, int z, int w) { if (x == z) { // この時には横方向の道 int ymin = min(y, w); return horizontal_cost.at(x - 1).at(ymin - 1); } else { int xmin = min(x, z); return vertical_cost.at(y - 1).at(xmin - 1); } } vector<P> dirs = {make_pair(1, 0), make_pair(-1, 0), make_pair(0, 1), make_pair(0, -1)}; int CityMap::count_highway(int num) { // dijkstra法で高速道路の数を調べる int x1 = A.at(num); int y1 = B.at(num); int x2 = C.at(num); int y2 = D.at(num); priority_queue<Td, vector<Td>, greater<Td>> pq; pq.emplace(0., 0, x1, y1); vector<vector<double>> cost_map(15, vector<double>(15, pow(10, 9))); while (!pq.empty()) { double cost; int count, x, y; tie(cost, count, x, y) = pq.top(); pq.pop(); // cerr << x << " " << y << " " << cost << " " << count << endl; if (cost_map.at(x).at(y) <= cost) continue; cost_map.at(x).at(y) = cost; if (x == x2 && y == y2) { return count; } for (int i = 0; i < 4; i++) { int dx, dy; tie(dx, dy) = dirs.at(i); int xx = x + dx; int yy = y + dy; if (xx <= 0 || xx >= 15 || yy <= 0 || yy >= 15) continue; double add_cost = cost_between(x, y, xx, yy); if (cost_map.at(xx).at(yy) < 10000) continue; int count2 = count; if (add_cost < 0.5) count2++; pq.emplace(cost + add_cost, count2, xx, yy); } } throw runtime_error("dijkstra must reach answer"); } int CityMap::calculate_income() { // dijkstra法で各人のベストなルートを探して、通る高速道路の本数を計算する int result = 0; for (int i = 0; i < N; i++) { // cerr << "i=" << i << " " << result << endl; result += 60 * count_highway(i); } return result; } vector<T4> road_plan; void make_road_plan() { road_plan = vector<T4>(); for (int x = 3; x < 12; x++) { if ((x - 3) % 4 < 2) { road_plan.push_back(make_tuple(x, 7, x + 1, 7)); road_plan.push_back(make_tuple(x, 9, x + 1, 9)); } else { road_plan.push_back(make_tuple(x, 4, x + 1, 4)); road_plan.push_back(make_tuple(x, 12, x + 1, 12)); } } for (int y = 3; y < 7; y++) { road_plan.push_back(make_tuple(3, y, 3, y + 1)); road_plan.push_back(make_tuple(5, y, 5, y + 1)); road_plan.push_back(make_tuple(7, y, 7, y + 1)); road_plan.push_back(make_tuple(9, y, 9, y + 1)); road_plan.push_back(make_tuple(11, y, 11, y + 1)); road_plan.push_back(make_tuple(13, y, 13, y + 1)); } for (int y = 9; y < 12; y++) { road_plan.push_back(make_tuple(3, y, 3, y + 1)); road_plan.push_back(make_tuple(5, y, 5, y + 1)); road_plan.push_back(make_tuple(7, y, 7, y + 1)); road_plan.push_back(make_tuple(9, y, 9, y + 1)); road_plan.push_back(make_tuple(11, y, 11, y + 1)); road_plan.push_back(make_tuple(13, y, 13, y + 1)); } } int main() { #ifdef OPTUNA_STUDY cerr << "optuna study, override parameters" << endl; #endif get_time(true); cin >> N >> T; A = vec_int(N); B = vec_int(N); C = vec_int(N); D = vec_int(N); rep(i, N) cin >> A.at(i) >> B.at(i) >> C.at(i) >> D.at(i); make_road_plan(); int a; int b; rep(i, 64) { cin >> a >> b; cout << "2" << endl; } int turn = 64; int cost_per_road = 1000 * 1000 * 10 / 8; // 1.25*10^6 int money = 1000 * 1000; CityMap city_map = CityMap(); int daily_income = 0; int road_ind = 0; int last_income_calculation = 0; while (turn < 300 && road_ind < road_plan.size()) { cin >> a >> b; // cerr << "turn:" << turn << " money:" << money << endl; // money = a; if (a != money) { int diff = a - money; daily_income += diff; money = a; } if (money >= cost_per_road) { int x, y, z, w; tie(x, y, z, w) = road_plan.at(road_ind); cout << "1 " << x << " " << y << " " << z << " " << w << endl; city_map.upgrade_road(x, y, z, w); // if (turn % 2 == 0) // { /* if (turn > last_income_calculation + 5) { daily_income = city_map.calculate_income(); last_income_calculation = turn; } */ //} money -= cost_per_road; road_ind++; } else { money += 50000; cout << "3" << endl; } money += daily_income; turn++; } while (turn < 400) { cin >> a >> b; cout << "3" << endl; money += daily_income; money += 50000; turn++; } cerr << "score:" << money << " time:" << get_time(false) << endl; return 0; }