結果
| 問題 | No.5024 魔法少女うなと宝集め |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-05-02 17:39:29 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 1,982 ms / 2,000 ms |
| コード長 | 4,295 bytes |
| 記録 | |
| コンパイル時間 | 2,573 ms |
| コンパイル使用メモリ | 218,656 KB |
| 実行使用メモリ | 6,400 KB |
| スコア | 1,978,609 |
| 最終ジャッジ日時 | 2026-05-02 17:41:13 |
| 合計ジャッジ時間 | 103,742 ms |
|
ジャッジサーバーID (参考情報) |
judge2_1 / judge3_1 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>
#include <random>
using namespace std;
vector<vector<int>> A;
int score(const vector<pair<int, int>>& path) {
int sum = 0;
for (const auto& p : path) {
sum += A[p.first][p.second];
}
return sum;
}
int main() {
double start_time = clock(); // 開始時間を記録
random_device seed_gen;
uint32_t seed = seed_gen();
default_random_engine engine(seed);
int N, T;
cin >> N >> T;
A.assign(N, vector<int>(N));
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cin >> A[i][j];
}
}
vector<pair<int, int>> path;
for (int i = 0; i < N; i++) {
if (i % 2 == 0) {
// 左から右へ
for (int j = 0; j < N; j++) {
path.push_back(make_pair(i, j));
if (path.size() == T) {
break;
}
}
} else {
// 右から左へ
for (int j = N - 1; j >= 0; j--) {
path.push_back(make_pair(i, j));
if (path.size() == T) {
break;
}
}
}
if (path.size() == T) {
break;
}
}
while((clock() - start_time) / CLOCKS_PER_SEC < 1.9) { // 1.9秒以内で繰り返す
double elapsed_time = (clock() - start_time) / CLOCKS_PER_SEC;
double elapsed_ratio = elapsed_time / 1.9; // 経過時間の割合
reverse(path.begin(), path.end()); // パスを反転させる
int current_score = score(path);
vector<pair<int, int>> old_path = path;
// ここでスコアを改善するためのロジックを実装
// ランダムな長さパスの端を削って,そこからランダムに歩かせる
double lambda = (double)0.7*T*(1.00001-elapsed_ratio); // 経過時間に応じてlambdaを減少させる
poisson_distribution<int> dist((int)lambda);
int length = min(T-1,max(1,dist(engine))); // ポアソン分布に従うランダムな長さ
path.erase(path.end() - length, path.end()); // パスの末尾からlength個削除
vector<vector<bool>>visited(N, vector<bool>(N, false));
for (const auto& p : path) {
visited[p.first][p.second] = true;
}
while(path.size() < T) {
pair<int, int> last = path.back();
vector<pair<int, int>> candidates;
if (last.first > 0) {
candidates.push_back(make_pair(last.first - 1, last.second)); // 上
}
if (last.first < N - 1) {
candidates.push_back(make_pair(last.first + 1, last.second)); // 下
}
if (last.second > 0) {
candidates.push_back(make_pair(last.first, last.second - 1)); // 左
}
if (last.second < N - 1) {
candidates.push_back(make_pair(last.first, last.second + 1)); // 右
}
for (auto it = candidates.begin(); it != candidates.end();) {
if (visited[it->first][it->second]) {
it = candidates.erase(it); // 既に訪れた場所は候補から削除
} else {
++it;
}
}
if (candidates.empty()) {
break; // 移動できる場所がない場合は終了
}
int idx = rand() % candidates.size(); // ランダムに候補から選択
path.push_back(candidates[idx]);
visited[candidates[idx].first][candidates[idx].second] = true; // 選択した場所を訪れたとマーク
}
if (path.size() < T) {
path = old_path; // パスがTに満たない場合は元に戻す
continue;
}
int new_score = score(path);
if (new_score < current_score) {
path = old_path; // スコアが改善しない場合は元に戻す
}
}
cout << path.size() << endl;
for (int k = 0; k < path.size(); k++) {
cout << path[k].first << " " << path[k].second << endl;
}
return 0;
}