結果
| 問題 |
No.5020 Averaging
|
| ユーザー |
e869120
|
| 提出日時 | 2024-02-24 13:16:17 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 944 ms / 1,000 ms |
| コード長 | 2,785 bytes |
| コンパイル時間 | 903 ms |
| コンパイル使用メモリ | 85,560 KB |
| 実行使用メモリ | 6,676 KB |
| スコア | 81,857,482 |
| 最終ジャッジ日時 | 2024-02-25 13:00:27 |
| 合計ジャッジ時間 | 49,957 ms |
|
ジャッジサーバーID (参考情報) |
judge14 / judge15 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
#include <iostream>
#include <cmath>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
const long long Target = 500000000000000000LL;
long long N;
long long A[59], LA[59];
long long B[59], LB[59];
long long Order[59], BestOrder[59];
// 現在のスコアを計算する関数 (操作は 50 手, i 回目の操作は U[i], V[i])
long long GetScore() {
for (int i = 1; i <= N; i++) LA[i] = A[i];
for (int i = 1; i <= N; i++) LB[i] = B[i];
for (int i = 1; i <= N - 1; i++) {
long long avgC = (LA[1] + LA[Order[i]]) / 2LL;
long long avgD = (LB[1] + LB[Order[i]]) / 2LL;
LA[1] = avgC; LA[Order[i]] = avgC;
LB[1] = avgD; LB[Order[i]] = avgD;
}
return max(abs(Target - LA[1]), abs(Target - LB[1]));
}
// ランダムな 0 以上 1 未満の乱数
long double Randouble() {
double s = 0.0, t = 1.0;
for (int i = 0; i < 3; i++) {
t /= 1024.0;
s += 1.0 * (rand() % 1024) * t;
}
return s;
}
int main() {
// Step 1. 入力
cin >> N;
for (int i = 1; i <= N; i++) cin >> A[i] >> B[i];
// Step 2. 焼きなまし法の初期値を決める
for (int i = 1; i <= N - 1; i++) Order[i] = i + 1;
long long CurrentScore = GetScore();
long long BestScore = CurrentScore;
int StartTime = clock();
// Step 3. 焼きなまし法 (0.15 秒)
while (clock() - StartTime <= 15 * CLOCKS_PER_SEC / 100) {
int idx1 = rand() % (N - 1) + 1;
int idx2 = rand() % (N - 1) + 1;
// 変更をする
swap(Order[idx1], Order[idx2]);
// スコアを計算
long long CandScore = GetScore();
double Diff = log10(CurrentScore) - log10(CandScore);
// 採用するか決定 [確率は exp(log10(スコアの悪化分)/0.2)]
if (Randouble() < exp(Diff / 0.2)) {
if (BestScore > CandScore) {
BestScore = CandScore;
for (int i = 1; i <= N - 1; i++) BestOrder[i] = Order[i];
}
CurrentScore = CandScore;
}
else {
swap(Order[idx1], Order[idx2]);
}
}
// Step 4. Order[1], ..., Order[10] を全探索
long long FinalScore = BestScore;
vector<int> Last10;
for (int i = 1; i <= 10; i++) Last10.push_back(BestOrder[i]);
sort(Last10.begin(), Last10.end());
do {
for (int i = 1; i <= N - 1; i++) {
if (i <= 10) Order[i] = Last10[i - 1];
else Order[i] = BestOrder[i];
}
// スコアを計算
long long CandScore = GetScore();
if (BestScore > CandScore) {
BestScore = CandScore;
for (int i = 1; i <= N - 1; i++) BestOrder[i] = Order[i];
}
} while (next_permutation(Last10.begin(), Last10.end()));
// Step 5. 答えを得る
vector<pair<int, int>> Answer;
for (int i = 1; i <= N - 1; i++) Answer.push_back(make_pair(1, BestOrder[i]));
// Step 6. 出力
cout << Answer.size() << endl;
for (int i = 0; i < Answer.size(); i++) cout << Answer[i].first << " " << Answer[i].second << endl;
return 0;
}
e869120