提出 #71725602


ソースコード 拡げる

import sys
import math
from heapq import heappush, heappop, nlargest
from copy import deepcopy

# 定数
TIME_LIMIT = 1.8  # 実行時間制限(少し余裕を持たせる)
BEAM_WIDTH = 50   # ビーム幅(PyPy3ならもっと増やせる可能性があります)

def solve():
    # --- 入力受取 ---
    # N: ID種類数(10), L: Level種類数(4), T: ターン数(500), K: 初期りんご
    N, L, T, K = map(int, sys.stdin.readline().split())
    
    # A: Level 0 の生産能力
    A = list(map(int, sys.stdin.readline().split()))
    
    # C: 初期コスト [Level][ID]
    C = []
    for _ in range(L):
        row = list(map(int, sys.stdin.readline().split()))
        C.append(row)

    # --- 前計算: 二項係数 ---
    # パスカルの三角形を用いて二項係数を事前計算
    # comb[n][k] = nCk
    # 最大500ターンなので 505 x 6 程度あれば十分(kは最大でもLevel数+1程度)
    comb = [[0] * 10 for _ in range(T + 10)]
    for i in range(T + 10):
        comb[i][0] = 1
        if i > 0:
            for j in range(1, 10):
                comb[i][j] = comb[i-1][j-1] + comb[i-1][j]

    # --- 状態クラスの定義 ---
    class State:
        def __init__(self, apples, B, P, history, turn):
            self.apples = apples
            self.B = B  # 機械の台数 [L][N]
            self.P = P  # 機械のパワー [L][N]
            self.history = history # 行動履歴
            self.turn = turn
            self.score = -1 # 評価値(未計算)

        def evaluate(self):
            """
            評価関数:
            「この時点からゲーム終了(Tターン)まで、一度も強化を行わなかった場合」の
            最終的なりんご総数を計算する。
            これを数学的公式(二項係数)で一発計算する。
            """
            remaining_turns = T - self.turn
            if remaining_turns <= 0:
                return self.apples

            predicted_apples = self.apples
            
            # 各機械について、残りの期間でどれだけりんごを生み出すか加算
            for j in range(N):
                # ID j の機械群が連携して生み出すりんご
                
                # 生産性ベース (A[j] * 全レベルのPの積)
                # 注: 実際は連鎖的に作用するが、簡易化のため系列ごとの係数を計算
                # 正確には、Level k の機械が Level 0 のりんごになるまで k ターン遅延し、
                # その寄与は パスカルの三角形(二項係数) に従う。
                
                # Level 0 の機械からの寄与
                # 毎ターン A[j] * P[0][j] * B[0][j]
                if self.P[0][j] > 0:
                    term = A[j] * self.B[0][j] * self.P[0][j]
                    predicted_apples += term * remaining_turns
                
                # Level 1以上の機械からの寄与
                # Level i の機械 1台は、tターン後に binom(t, i+1) 個のりんご生産に寄与する(概算)
                # 厳密には、間のLevelのPowerも掛け算される
                
                # 高速化のため、影響力が大きい系列のみ計算、あるいはDP的に解くべきだが
                # ここでは「現在の構成で放置した場合の厳密解」を計算する
                
                # Pの累積積を計算 (prod_P[i] = P[0][j] * ... * P[i][j])
                # ただしP=0が含まれるとそれより上流は機能しない
                
                current_prod = A[j]
                for i in range(L):
                    if self.P[i][j] == 0:
                        break # これより上のレベルは下のレベルを動かせない
                    
                    current_prod *= self.P[i][j]
                    
                    # Level i の機械 B[i][j] 台が残り R ターンで生む総量
                    # 公式: Total += B[i][j] * (A * ΠP) * binom(R, i+1)
                    # binom(R, i+1) は、「残りRターンで、i回の積分(累積和)を経て得られる総和」
                    
                    term = self.B[i][j] * current_prod * comb[remaining_turns][i+1]
                    predicted_apples += term
            
            return predicted_apples

        def __lt__(self, other):
            # heapqは最小値を取り出すため、逆にして最大ヒープのように振る舞わせる
            # ただし、今回は nlargest を使うので、単純に score で比較できれば良い
            return self.score < other.score

    # --- 初期状態 ---
    # B: 全て1, P: 全て0
    init_B = [[1] * N for _ in range(L)]
    init_P = [[0] * N for _ in range(L)]
    
    initial_state = State(K, init_B, init_P, [], 0)
    initial_state.score = initial_state.evaluate()
    
    beam = [initial_state]

    # --- ターン進行 ---
    for t in range(T):
        next_beam = []
        
        # 候補の手を列挙して次状態を作成
        # ビーム内の各状態について
        for state in beam:
            # 1. 何もしない (常に選択可能)
            # コスト0。ただし、自動生産フェーズは必ず走る
            
            # まず、このターンでの自動生産(Bの増加とりんごの増加)を計算しておく
            # 次の状態のベースとなる B と apples
            next_B = [row[:] for row in state.B]
            produced_apples = 0
            
            # Level 0, 1, 2, 3 の順に処理 (問題文準拠)
            # Level 0: りんご増加
            for j in range(N):
                produced_apples += A[j] * state.B[0][j] * state.P[0][j]
            
            # Level 1以上: 1つ下のレベルの機械数増加
            for i in range(1, L):
                for j in range(N):
                    next_B[i-1][j] += state.B[i][j] * state.P[i][j]
            
            base_next_apples = state.apples + produced_apples
            
            # 行動A: 何もしない (-1)
            # 常に候補に入れる
            no_op_state = State(
                base_next_apples, 
                next_B, 
                state.P, # Pは変わらない
                state.history + [-1], 
                t + 1
            )
            no_op_state.score = no_op_state.evaluate()
            next_beam.append(no_op_state)

            # 行動B: 強化する (i, j)
            # 全ての (i, j) を試すと 40 通り。ビーム幅50だと 2000 状態生成。
            # 重すぎれば、コストが払えるものだけに絞るなどの枝刈りが可能。
            
            for i in range(L):
                for j in range(N):
                    cost = C[i][j] * (state.P[i][j] + 1)
                    
                    # コストが払えるかチェック (state.apples を使う。自動生産分はこのターン使えない)
                    if state.apples >= cost:
                        # 強化実行
                        new_P = [row[:] for row in state.P]
                        new_P[i][j] += 1
                        
                        # りんご消費
                        rem_apples = base_next_apples - cost
                        
                        # 新しい状態
                        upg_state = State(
                            rem_apples,
                            next_B,
                            new_P,
                            state.history + [i * N + j], # 履歴には便宜上整数を入れる、出力時に変換
                            t + 1
                        )
                        upg_state.score = upg_state.evaluate()
                        next_beam.append(upg_state)

        # 上位 K 個を残す (Beam Search)
        # スコア(将来予測される最終りんご数)が高い順
        beam = nlargest(BEAM_WIDTH, next_beam, key=lambda s: s.score)

    # --- 結果出力 ---
    best_state = beam[0]
    
    # 履歴をデコードして出力
    for action in best_state.history:
        if action == -1:
            print("-1")
        else:
            i = action // N
            j = action % N
            print(f"{i} {j}")

# --- 実行 ---
if __name__ == "__main__":
    solve()

提出情報

提出日時
問題 A - Apple Incremental Game
ユーザ kuruma_zensoku
言語 Python (PyPy 3.11-v7.3.20)
得点 727586524
コード長 8634 Byte
結果 AC
実行時間 1038 ms
メモリ 577260 KiB

ジャッジ結果

セット名 test_ALL
得点 / 配点 727586524 / 150000000000
結果
AC × 150
セット名 テストケース
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
ケース名 結果 実行時間 メモリ
test_0000.txt AC 860 ms 558332 KiB
test_0001.txt AC 1038 ms 569536 KiB
test_0002.txt AC 641 ms 500696 KiB
test_0003.txt AC 815 ms 565468 KiB
test_0004.txt AC 736 ms 553200 KiB
test_0005.txt AC 788 ms 565720 KiB
test_0006.txt AC 807 ms 555744 KiB
test_0007.txt AC 766 ms 568912 KiB
test_0008.txt AC 789 ms 557036 KiB
test_0009.txt AC 845 ms 576460 KiB
test_0010.txt AC 818 ms 562180 KiB
test_0011.txt AC 799 ms 556192 KiB
test_0012.txt AC 781 ms 567924 KiB
test_0013.txt AC 687 ms 532832 KiB
test_0014.txt AC 751 ms 552948 KiB
test_0015.txt AC 793 ms 566792 KiB
test_0016.txt AC 670 ms 508292 KiB
test_0017.txt AC 777 ms 564512 KiB
test_0018.txt AC 808 ms 566740 KiB
test_0019.txt AC 802 ms 565916 KiB
test_0020.txt AC 870 ms 569560 KiB
test_0021.txt AC 705 ms 546604 KiB
test_0022.txt AC 826 ms 560172 KiB
test_0023.txt AC 749 ms 561360 KiB
test_0024.txt AC 641 ms 485404 KiB
test_0025.txt AC 505 ms 346356 KiB
test_0026.txt AC 846 ms 561892 KiB
test_0027.txt AC 657 ms 485316 KiB
test_0028.txt AC 748 ms 547916 KiB
test_0029.txt AC 705 ms 504476 KiB
test_0030.txt AC 812 ms 567920 KiB
test_0031.txt AC 786 ms 561084 KiB
test_0032.txt AC 809 ms 562272 KiB
test_0033.txt AC 754 ms 561952 KiB
test_0034.txt AC 716 ms 553776 KiB
test_0035.txt AC 680 ms 520364 KiB
test_0036.txt AC 790 ms 563064 KiB
test_0037.txt AC 738 ms 564904 KiB
test_0038.txt AC 837 ms 565468 KiB
test_0039.txt AC 585 ms 425792 KiB
test_0040.txt AC 654 ms 480644 KiB
test_0041.txt AC 728 ms 503488 KiB
test_0042.txt AC 798 ms 557608 KiB
test_0043.txt AC 834 ms 568740 KiB
test_0044.txt AC 722 ms 554804 KiB
test_0045.txt AC 574 ms 413968 KiB
test_0046.txt AC 597 ms 438004 KiB
test_0047.txt AC 801 ms 568280 KiB
test_0048.txt AC 673 ms 502556 KiB
test_0049.txt AC 773 ms 568748 KiB
test_0050.txt AC 896 ms 566588 KiB
test_0051.txt AC 869 ms 570736 KiB
test_0052.txt AC 807 ms 560040 KiB
test_0053.txt AC 775 ms 567428 KiB
test_0054.txt AC 757 ms 557564 KiB
test_0055.txt AC 775 ms 557148 KiB
test_0056.txt AC 808 ms 563332 KiB
test_0057.txt AC 816 ms 561932 KiB
test_0058.txt AC 878 ms 564068 KiB
test_0059.txt AC 827 ms 560560 KiB
test_0060.txt AC 864 ms 568132 KiB
test_0061.txt AC 821 ms 562796 KiB
test_0062.txt AC 724 ms 551544 KiB
test_0063.txt AC 833 ms 561580 KiB
test_0064.txt AC 859 ms 567772 KiB
test_0065.txt AC 783 ms 570660 KiB
test_0066.txt AC 823 ms 566584 KiB
test_0067.txt AC 586 ms 444604 KiB
test_0068.txt AC 776 ms 568328 KiB
test_0069.txt AC 850 ms 564440 KiB
test_0070.txt AC 733 ms 533680 KiB
test_0071.txt AC 618 ms 447176 KiB
test_0072.txt AC 819 ms 561620 KiB
test_0073.txt AC 733 ms 563048 KiB
test_0074.txt AC 856 ms 574576 KiB
test_0075.txt AC 413 ms 269268 KiB
test_0076.txt AC 851 ms 564440 KiB
test_0077.txt AC 855 ms 555652 KiB
test_0078.txt AC 795 ms 556896 KiB
test_0079.txt AC 815 ms 568356 KiB
test_0080.txt AC 843 ms 571860 KiB
test_0081.txt AC 806 ms 570040 KiB
test_0082.txt AC 853 ms 569544 KiB
test_0083.txt AC 749 ms 561884 KiB
test_0084.txt AC 781 ms 569444 KiB
test_0085.txt AC 718 ms 536500 KiB
test_0086.txt AC 650 ms 445136 KiB
test_0087.txt AC 893 ms 556144 KiB
test_0088.txt AC 865 ms 570608 KiB
test_0089.txt AC 851 ms 555508 KiB
test_0090.txt AC 870 ms 561940 KiB
test_0091.txt AC 427 ms 297316 KiB
test_0092.txt AC 843 ms 566416 KiB
test_0093.txt AC 479 ms 325248 KiB
test_0094.txt AC 555 ms 373200 KiB
test_0095.txt AC 723 ms 544292 KiB
test_0096.txt AC 765 ms 553564 KiB
test_0097.txt AC 867 ms 555384 KiB
test_0098.txt AC 764 ms 567128 KiB
test_0099.txt AC 671 ms 486008 KiB
test_0100.txt AC 797 ms 559300 KiB
test_0101.txt AC 604 ms 434032 KiB
test_0102.txt AC 891 ms 566552 KiB
test_0103.txt AC 375 ms 222184 KiB
test_0104.txt AC 823 ms 570244 KiB
test_0105.txt AC 876 ms 563880 KiB
test_0106.txt AC 841 ms 565892 KiB
test_0107.txt AC 888 ms 568152 KiB
test_0108.txt AC 881 ms 576232 KiB
test_0109.txt AC 697 ms 498052 KiB
test_0110.txt AC 830 ms 567752 KiB
test_0111.txt AC 897 ms 566164 KiB
test_0112.txt AC 807 ms 563280 KiB
test_0113.txt AC 894 ms 566452 KiB
test_0114.txt AC 835 ms 568724 KiB
test_0115.txt AC 809 ms 575256 KiB
test_0116.txt AC 796 ms 562984 KiB
test_0117.txt AC 809 ms 560740 KiB
test_0118.txt AC 821 ms 570296 KiB
test_0119.txt AC 781 ms 557564 KiB
test_0120.txt AC 814 ms 570180 KiB
test_0121.txt AC 573 ms 397008 KiB
test_0122.txt AC 896 ms 562436 KiB
test_0123.txt AC 883 ms 567028 KiB
test_0124.txt AC 888 ms 558948 KiB
test_0125.txt AC 556 ms 401364 KiB
test_0126.txt AC 713 ms 535772 KiB
test_0127.txt AC 802 ms 566400 KiB
test_0128.txt AC 883 ms 571788 KiB
test_0129.txt AC 866 ms 570612 KiB
test_0130.txt AC 833 ms 570080 KiB
test_0131.txt AC 802 ms 563372 KiB
test_0132.txt AC 750 ms 561532 KiB
test_0133.txt AC 881 ms 566232 KiB
test_0134.txt AC 709 ms 514316 KiB
test_0135.txt AC 859 ms 566268 KiB
test_0136.txt AC 857 ms 569408 KiB
test_0137.txt AC 845 ms 568020 KiB
test_0138.txt AC 605 ms 452092 KiB
test_0139.txt AC 831 ms 566524 KiB
test_0140.txt AC 701 ms 548760 KiB
test_0141.txt AC 823 ms 559472 KiB
test_0142.txt AC 864 ms 568288 KiB
test_0143.txt AC 826 ms 568132 KiB
test_0144.txt AC 437 ms 277524 KiB
test_0145.txt AC 767 ms 577260 KiB
test_0146.txt AC 645 ms 476388 KiB
test_0147.txt AC 783 ms 561672 KiB
test_0148.txt AC 917 ms 566212 KiB
test_0149.txt AC 854 ms 569892 KiB