結果
| 問題 |
No.5016 Worst Mayor
|
| コンテスト | |
| ユーザー |
e869120
|
| 提出日時 | 2023-04-28 21:46:19 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,622 ms / 2,000 ms |
| コード長 | 5,288 bytes |
| コンパイル時間 | 1,126 ms |
| コンパイル使用メモリ | 90,780 KB |
| 実行使用メモリ | 26,528 KB |
| スコア | 11,924,530,380 |
| 平均クエリ数 | 400.00 |
| 最終ジャッジ日時 | 2023-04-29 12:33:09 |
| 合計ジャッジ時間 | 86,421 ms |
|
ジャッジサーバーID (参考情報) |
judge11 / judge15 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
#include <iostream>
#include <vector>
#include <tuple>
#include <cmath>
#include <algorithm>
using namespace std;
// Input Information
int DEBUG = 1;
int N, T;
int A[3009], B[3009], C[3009], D[3009];
int CurrentMoney, DebugMoney = 1000000;
int CurrentCorps, DebugCorps = 1;
// Other Variables
int Build[1009];
int Money[2000009];
int Cost[199][199];
int D1[15][16];
int D2[16][15];
// Initialize Money
void Initialize() {
for (int i = 0; i <= 1000; i++) {
for (int j = 0; j < 1000; j++) {
Money[1000 * i + 223 * j] = 60 * j;
}
}
for (int i = 1; i <= 1000; i++) {
Build[i] = (int)(10000000.0 / sqrt(1.0 * i));
}
}
// Get Total Earned Money
int GetEarnedMoney() {
for (int i = 0; i < 196; i++) {
for (int j = 0; j < 196; j++) Cost[i][j] = 1000000;
Cost[i][i] = 0;
}
// Initialize Cost
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 14; j++) {
int a1 = (i + 0) * 14 + (j + 0);
int a2 = (i + 1) * 14 + (j + 0);
if (D1[i][j] == 1) {
Cost[a1][a2] = 223;
Cost[a2][a1] = 223;
}
else {
Cost[a1][a2] = 1000;
Cost[a2][a1] = 1000;
}
}
}
for (int i = 0; i < 14; i++) {
for (int j = 0; j < 13; j++) {
int a1 = (i + 0) * 14 + (j + 0);
int a2 = (i + 0) * 14 + (j + 1);
if (D2[i][j] == 1) {
Cost[a1][a2] = 223;
Cost[a2][a1] = 223;
}
else {
Cost[a1][a2] = 1000;
Cost[a2][a1] = 1000;
}
}
}
// Warshall-Floyd
for (int k = 0; k < 196; k++) {
for (int i = 0; i < 196; i++) {
for (int j = 0; j < 196; j++) Cost[i][j] = min(Cost[i][j], Cost[i][k] + Cost[k][j]);
}
}
int sum = 0;
for (int i = 1; i <= N; i++) {
int pos1 = (A[i] - 1) * 14 + (B[i] - 1);
int pos2 = (C[i] - 1) * 14 + (D[i] - 1);
sum += Money[Cost[pos1][pos2]];
}
return sum;
}
double Randouble() {
double s = 0, t = 1;
for (int i = 0; i < 3; i++) {
t /= 1024.0;
s += 1.0 * (rand() % 1024) * t;
}
return s;
}
void Ask(int a1, int a2, int a3, int a4, int a5) {
if (DEBUG == 1) {
if (a1 == 1) cout << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << endl;
if (a1 == 2) cout << a1 << endl;
if (a1 == 3) cout << a1 << endl;
}
if (DEBUG == 2) {
if (a1 == 1) {
if (a2 > a4) { swap(a2, a4); swap(a3, a5); }
if (a3 > a5) { swap(a2, a4); swap(a3, a5); }
if (a3 == a5) D1[a2 - 1][a3 - 1] = 1;
if (a2 == a4) D2[a2 - 1][a3 - 1] = 1;
DebugMoney -= Build[DebugCorps];
}
if (a1 == 2) {
DebugCorps += 1;
}
if (a1 == 3) {
DebugMoney += 50000;
}
DebugMoney += GetEarnedMoney();
}
}
int main() {
Initialize();
cin >> N >> T;
for (int i = 1; i <= N; i++) cin >> A[i] >> B[i] >> C[i] >> D[i];
// Start Yakinamashi
int CurrentScore = GetEarnedMoney();
int ti = clock();
int loop = 0;
while (clock() - ti < 1.5 * CLOCKS_PER_SEC) {
loop++;
double temp = 400.0 * (1.0 - 1.0 * (clock() - ti) / (1.5 * CLOCKS_PER_SEC));
int ty = rand() % 2;
int px = rand() % 14; if (ty == 0 && px == 13) continue;
int py = rand() % 14; if (ty == 1 && py == 13) continue;
if (ty == 0) D1[px][py] ^= 1;
if (ty == 1) D2[px][py] ^= 1;
int CandScore = GetEarnedMoney();
if (Randouble() < exp(1.0 * (CandScore - CurrentScore) / temp)) {
CurrentScore = CandScore;
}
else {
if (ty == 0) D1[px][py] ^= 1;
if (ty == 1) D2[px][py] ^= 1;
}
}
// Calculate the Order of Adding Edges
vector<tuple<int, int, int, int, int>> Edges;
for (int i = 0; i < 14; i++) {
for (int j = 0; j < 13; j++) {
if (D2[i][j] == 0) continue;
int dst1 = abs(13 - 2 * (i + 0)) * abs(13 - 2 * (i + 0)) + abs(13 - 2 * (j + 0)) * abs(13 - 2 * (j + 0));
int dst2 = abs(13 - 2 * (i + 0)) * abs(13 - 2 * (i + 0)) + abs(13 - 2 * (j + 1)) * abs(13 - 2 * (j + 1));
Edges.push_back(make_tuple(dst1 + dst2, i, j, i, j + 1));
}
}
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 14; j++) {
if (D1[i][j] == 0) continue;
int dst1 = abs(13 - 2 * (i + 0)) * abs(13 - 2 * (i + 0)) + abs(13 - 2 * (j + 0)) * abs(13 - 2 * (j + 0));
int dst2 = abs(13 - 2 * (i + 1)) * abs(13 - 2 * (i + 1)) + abs(13 - 2 * (j + 0)) * abs(13 - 2 * (j + 0));
Edges.push_back(make_tuple(dst1 + dst2, i, j, i + 1, j));
}
}
sort(Edges.begin(), Edges.end());
// Reset D1, D2 for Debug
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 14; j++) D1[i][j] = 0;
}
for (int i = 0; i < 14; i++) {
for (int j = 0; j < 13; j++) D2[i][j] = 0;
}
// Answer Query
int BuiltRoads = 0;
for (int i = 1; i <= T; i++) {
if (DEBUG == 1) {
cin >> CurrentMoney >> CurrentCorps;
if (CurrentMoney == -1 && CurrentCorps == -1) break;
}
if (DEBUG == 2) {
CurrentMoney = DebugMoney;
CurrentCorps = DebugCorps;
}
fprintf(stderr, "Turn =% 4d, Money=% 10d, Corps =% 3d, Roads =% 3d/%d\n", i, CurrentMoney, CurrentCorps, BuiltRoads, (int)Edges.size());
// Get Acts
if (i <= 50) {
Ask(2, -1, -1, -1, -1);
}
else if (BuiltRoads == (int)Edges.size() || i >= 250) {
Ask(3, -1, -1, -1, -1);
}
else if (BuiltRoads >= 3 && CurrentMoney < Build[CurrentCorps]) {
Ask(2, -1, -1, -1, -1);
}
else if (BuiltRoads <= 2 && CurrentMoney < Build[CurrentCorps]) {
Ask(3, -1, -1, -1, -1);
}
else {
Ask(1, get<1>(Edges[BuiltRoads]) + 1, get<2>(Edges[BuiltRoads]) + 1, get<3>(Edges[BuiltRoads]) + 1, get<4>(Edges[BuiltRoads]) + 1);
BuiltRoads += 1;
}
}
return 0;
}
e869120