AtCoder Heuristic First-step Vol.1 - 変数・関数一覧と疑似コード

貪欲法の変数一覧

変数名説明
order_count注文の総数(固定値 1000)
pickup_count高橋くんが処理する注文の数(固定値 50)
officeAtCoderオフィスの座標 (400, 400) スタート地点、かつゴール地点
restaurantsレストランの座標リスト
destinations目的地(配達先)の座標リスト
orders選択した注文のリスト
route訪問するルートのリスト
visited_restaurant訪問済みのレストランを記録する
current_position現在地
total_dist総移動距離

貪欲法の関数一覧

関数名説明
int Point::dist(const Point& p)2つの点のマンハッタン距離を計算する
static Input Input::read()入力データを読み取る
void Output::print()解を出力する
Output solve(const Input& input)問題を解く

貪欲法の疑似コード

// --- メインの処理 ---
関数 solve(input: Input) -> Output:

    変数 orders ← 空のリスト
    変数 route ← 空のリスト
    変数 visited_restaurant ← 長さ input.order_countfalse 配列

    routeinput.office を追加
    変数 current_positioninput.office
    変数 total_dist0

    ループ (50回): 最も近いレストランを訪問
    ループ (50回): 最も近い配達先を訪問
    routeinput.office を追加
    total_dist 更新

    戻り値 Output(orders, route)
    

貪欲法の出力例

50 709 217 838 931 774 366 278 474 538 515 458 970 96 269 744 360 490 107 804 836 995 171 497 408 166 312 813 58 708 915 610 850 715 657 693 418 333 419 688 263 355 656 743 924 325 234 290 449 951 755
102 400 400 407 397 385 394 379 410 381 412 386 434 408 436 441 440 439 463 430 457 416 477 426 488 399 493 372 493 360 493 345 486 335 501 335 512 305 509 298 495 287 516 288 529 276 528 278 539 306 536 310 529 321 539 322 564 335 560 333 555 337 566 323 590 322 589 324 605 355 600 367 602 378 596 385 584 385 566 395 571 407 578 409 579 371 579 367 530 389 525 424 527 422 535 436 529 434 526 451 514 461 521 480 592 604 522 584 472 565 430 556 427 552 316 487 284 450 286 422 198 372 61 359 27 286 69 275 121 270 135 289 137 206 136 157 131 36 62 2 39 0 251 63 355 106 336 109 429 232 482 242 528 235 670 248 682 239 759 136 742 125 668 68 652 7 688 33 799 292 315 263 254 494 369 683 406 757 407 762 353 700 328 677 254 648 120 619 106 578 50 570 34 778 148 778 151 708 532 791 626 797 651 400 400
    

貪欲法の標準エラー出力

0番目のレストラン: p_708 = (407, 397)
1番目のレストラン: p_216 = (385, 394)
2番目のレストラン: p_837 = (379, 410)
3番目のレストラン: p_930 = (381, 412)
4番目のレストラン: p_773 = (386, 434)
5番目のレストラン: p_365 = (408, 436)
6番目のレストラン: p_277 = (441, 440)
7番目のレストラン: p_473 = (439, 463)
8番目のレストラン: p_537 = (430, 457)
9番目のレストラン: p_514 = (416, 477)
10番目のレストラン: p_457 = (426, 488)
11番目のレストラン: p_969 = (399, 493)
12番目のレストラン: p_95 = (372, 493)
13番目のレストラン: p_268 = (360, 493)
14番目のレストラン: p_743 = (345, 486)
15番目のレストラン: p_359 = (335, 501)
16番目のレストラン: p_489 = (335, 512)
17番目のレストラン: p_106 = (305, 509)
18番目のレストラン: p_803 = (298, 495)
19番目のレストラン: p_835 = (287, 516)
20番目のレストラン: p_994 = (288, 529)
21番目のレストラン: p_170 = (276, 528)
22番目のレストラン: p_496 = (278, 539)
23番目のレストラン: p_407 = (306, 536)
24番目のレストラン: p_165 = (310, 529)
25番目のレストラン: p_311 = (321, 539)
26番目のレストラン: p_812 = (322, 564)
27番目のレストラン: p_57 = (335, 560)
28番目のレストラン: p_707 = (333, 555)
29番目のレストラン: p_914 = (337, 566)
30番目のレストラン: p_609 = (323, 590)
31番目のレストラン: p_849 = (322, 589)
32番目のレストラン: p_714 = (324, 605)
33番目のレストラン: p_656 = (355, 600)
34番目のレストラン: p_692 = (367, 602)
35番目のレストラン: p_417 = (378, 596)
36番目のレストラン: p_332 = (385, 584)
37番目のレストラン: p_418 = (385, 566)
38番目のレストラン: p_687 = (395, 571)
39番目のレストラン: p_262 = (407, 578)
40番目のレストラン: p_354 = (409, 579)
41番目のレストラン: p_655 = (371, 579)
42番目のレストラン: p_742 = (367, 530)
43番目のレストラン: p_923 = (389, 525)
44番目のレストラン: p_324 = (424, 527)
45番目のレストラン: p_233 = (422, 535)
46番目のレストラン: p_289 = (436, 529)
47番目のレストラン: p_448 = (434, 526)
48番目のレストラン: p_950 = (451, 514)
49番目のレストラン: p_754 = (461, 521)
0番目の配達先: q_268 = (480, 592)
1番目の配達先: q_754 = (604, 522)
2番目の配達先: q_687 = (584, 472)
3番目の配達先: q_773 = (565, 430)
4番目の配達先: q_262 = (556, 427)
5番目の配達先: q_849 = (552, 316)
6番目の配達先: q_969 = (487, 284)
7番目の配達先: q_692 = (450, 286)
8番目の配達先: q_609 = (422, 198)
9番目の配達先: q_354 = (372, 61)
10番目の配達先: q_994 = (359, 27)
11番目の配達先: q_714 = (286, 69)
12番目の配達先: q_332 = (275, 121)
13番目の配達先: q_106 = (270, 135)
14番目の配達先: q_277 = (289, 137)
15番目の配達先: q_914 = (206, 136)
16番目の配達先: q_923 = (157, 131)
17番目の配達先: q_707 = (36, 62)
18番目の配達先: q_95 = (2, 39)
19番目の配達先: q_170 = (0, 251)
20番目の配達先: q_407 = (63, 355)
21番目の配達先: q_656 = (106, 336)
22番目の配達先: q_57 = (109, 429)
23番目の配達先: q_289 = (232, 482)
24番目の配達先: q_418 = (242, 528)
25番目の配達先: q_514 = (235, 670)
26番目の配達先: q_473 = (248, 682)
27番目の配達先: q_233 = (239, 759)
28番目の配達先: q_365 = (136, 742)
29番目の配達先: q_950 = (125, 668)
30番目の配達先: q_803 = (68, 652)
31番目の配達先: q_457 = (7, 688)
32番目の配達先: q_708 = (33, 799)
33番目の配達先: q_165 = (292, 315)
34番目の配達先: q_417 = (263, 254)
35番目の配達先: q_837 = (494, 369)
36番目の配達先: q_216 = (683, 406)
37番目の配達先: q_835 = (757, 407)
38番目の配達先: q_448 = (762, 353)
39番目の配達先: q_742 = (700, 328)
40番目の配達先: q_537 = (677, 254)
41番目の配達先: q_743 = (648, 120)
42番目の配達先: q_311 = (619, 106)
43番目の配達先: q_489 = (578, 50)
44番目の配達先: q_655 = (570, 34)
45番目の配達先: q_812 = (778, 148)
46番目の配達先: q_359 = (778, 151)
47番目の配達先: q_930 = (708, 532)
48番目の配達先: q_324 = (791, 626)
49番目の配達先: q_496 = (797, 651)
total distance: 7918

追加された変数一覧(山登り法)

変数名説明
candidatesオフィスから距離400以下の注文の候補リスト(注文のインデックス)
destinations【※入力のdestinationsとは別】選択した注文に対応する配達先のインデックスリスト(solve_greedy内でordersをコピー)
current_distsolve_hill_climbing内で現在の経路の総移動距離
rand乱数生成器(std::mt19937、固定シード42)
start_time山登り法の開始時刻
time_limit山登り法の制限時間(1900ミリ秒)
iteration山登り法の試行回数のカウンタ
iランダムに選ばれる、訪問先(配達先)のルート内インデックス(オフィス・レストラン部分を除く)
jランダムに選ばれる、訪問先(配達先)のルート内インデックス
point_to_movei番目の訪問先を移動する際の対象ポイント(Point型)
new_dist操作後に再計算された経路の総移動距離

山登り法による経路改善の疑似コード

 // 山登り法による経路改善 関数 solve_hill_climbing(input: Input, output_greedy: Output) -> Output: // 初期解のコピー ordersoutput_greedy.orders routeoutput_greedy.route current_distget_distance(route)
php-template
コピーする
rand ← 乱数生成器(シード=42)
start_time ← 現在時刻
time_limit1900 // ミリ秒
iteration0

while (現在時刻 - start_time < time_limit) do:
    // ランダムに2つのインデックスを選ぶ (配達先部分のみ)
    irand() % pickup_count + pickup_count + 1
    jrand() % pickup_count + pickup_count + 1

    // i番目の訪問先を j番目に移動する
    point_to_moveroute[i]
    route.remove(i)
    route.insert(j, point_to_move)

    new_distget_distance(route)
    if new_distcurrent_dist then:
        if new_dist < current_dist then:
            標準エラー出力に "iteration: " + iteration + ", total distance: " + new_dist
        current_distnew_dist
    else:
        // 悪化している場合は元に戻す
        route.remove(j)
        route.insert(i, point_to_move)
    iterationiteration + 1

標準エラー出力に "--- Result ---"
標準エラー出力に "iteration: " + iteration + ", total distance: " + current_dist
return Output(orders, route)

追加された変数一覧(焼きなまし法)

変数名説明
orderssolve_simulated_annealing内で初期解としてコピーされた、選択した注文のリスト
routesolve_simulated_annealing内で初期解としてコピーされた配達ルート
current_dist初期解の経路の総移動距離(get_distance(route)で計算)
rand乱数生成器(std::mt19937、固定シード42)
zero_one_dist0.0以上1.0未満の乱数を生成する分布(std::uniform_real_distribution
start_time焼きなまし法の開始時刻(std::chrono::system_clock::now()で取得)
time_limit焼きなまし法の制限時間(1900ミリ秒)
start_temperature焼きなまし法の開始温度(2e2)
end_temperature焼きなまし法の終了温度(1e0)
current_temperature現在の温度(温度更新に利用)
iteration焼きなまし法の試行回数カウンタ
iランダムに選ばれる、訪問先(配達先)のルート内インデックス(オフィス・レストラン部分を除く)
jランダムに選ばれる、訪問先(配達先)のルート内インデックス
point_to_movei番目の訪問先を移動する際の対象ポイント(Point型)
new_dist操作後に再計算された経路の総移動距離
progress経過時間の割合(温度更新に利用、0.0~1.0)

焼きなまし法による経路改善の疑似コード

 // 焼きなまし法による経路改善 関数 solve_simulated_annealing(input: Input, output_greedy: Output) -> Output: // 初期解のコピー ordersoutput_greedy.orders のコピー routeoutput_greedy.route のコピー current_distget_distance(route)
php-template
コピーする
rand ← 乱数生成器(シード=42)
zero_one_dist ← 乱数分布(0.0, 1.0)
start_time ← 現在時刻
time_limit1900 // ミリ秒

start_temperature200.0 // 2e2
end_temperature1.0   // 1e0
current_temperaturestart_temperature
iteration0

while (現在時刻 - start_time  time_limit) do:
    // ランダムに2つのインデックスを選ぶ (配達先部分のみ)
    irand() % pickup_count + pickup_count + 1
    jrand() % pickup_count + pickup_count + 1

    // i番目の訪問先を j番目に移動する
    point_to_moveroute[i]
    route.remove(i)
    route.insert(j, point_to_move)

    new_distget_distance(route)
    if new_distcurrent_dist or (zero_one_dist(rand) < exp((current_dist - new_dist) / current_temperature)) then:
        current_distnew_dist
    else:
        // 変更を元に戻す
        route.remove(j)
        route.insert(i, point_to_move)
    iterationiteration + 1

    if (iteration mod 100000 = 0) then:
        標準エラー出力に "iteration: " + iteration + ", total distance: " + current_dist

    progress ← (現在時刻 - start_time) / time_limit // 0.0〜1.0の割合
    current_temperature ← (start_temperature^(1.0 - progress)) * (end_temperature^(progress))

標準エラー出力に "--- Result ---"
標準エラー出力に "iteration: " + iteration + ", total distance: " + current_dist
return Output(orders, route)