[規格]11048号:モバイル/Python/ダイナミックプログラミング(DP)


移動


  • 質問する
    ジュンギュはNです.×Mサイズの迷宮に閉じ込められています.迷宮×一つの大きさの部屋に分かれていて、それぞれの部屋にキャンディが置いてあります.迷宮の最左上は(1,1),最右下は(N,M)である.
    ジュンギュは現在(1,1)、(N,M)に移動する予定です.ジュンギュが(r,c),(r+1,c),(r,c+1),(r+1,c+1)に移動すれば,各部屋を訪問するたびに部屋に置いてあるキャンディを持ち去ることができる.そして、迷宮から出られない.
    ジュンギュが(N,M)に移動すると、持ってくるキャンディの個数の最値を求める.

  • 入力
    最初の行は迷路の大きさN,Mを与える.(1 ≤ N, M ≤ 1,000)
    2行目からN行にはM個の数字があり、r行のc番は(r,c)に置かれたキャンディの個数である.糖の個数は0以上、100以下である.

  • しゅつりょく
    1行目のジュンギュが(N,M)に移動すると、導入可能なキャンディの数が出力される.
  • 私の答え

  • の2 Dテーブルを使用した動的プログラミングの問題.迷宮の全位置については、1. 위에서 오는 경우 2. 왼쪽에서 오는 경우 3. 왼쪽 대각선 위에서 오는 경우の中で最も多いキャンディをDPテーブルに保存し、最終到着位置に更新すればよい.
  • N, M = map(int, input().split())
    miro = []
    for _ in range(N):
        miro.append(list(map(int, input().split())))
        
    for i in range(N):
        for j in range(M):
            # 위에서 오는 경우
            if i == 0:
                up =  0
            else:
                up = miro[i - 1][j]
            
            # 왼쪽에서 오는 경우
            if j == 0:
                left = 0
            else:
                left = miro[i][j - 1]
            
            # 왼쪽 대각선 위에서 오는 경우
            if i > 0 and j > 0:
                left_up = miro[i - 1][j - 1]
            else:
                left_up = 0
                
            miro[i][j] += max(up, left, left_up)
                
    print(miro[N - 1][M - 1])

    別の解釈

  • 対角線経路を考慮する必要はありません.対角線への移動は、右に曲がってから下に移動したり、下に移動して右に曲がったりする場合よりも絶対に大きな値を得ることができないからです.
  • また,不便な計算を減らすためにdpテーブルを横,縦各1格子に分割する.
  • N, M = map(int, input().split())
    miro = []
    for _ in range(N):
        miro.append(list(map(int, input().split())))
        
    dp = [[0] * (M + 1) for _ in range(N + 1)] # 한 칸씩 늘린 dp 테이블
    # dp 테이블 초기화
    for i in range(N):
        for j in range(M):
            dp[i + 1][j + 1] = miro[i][j]
            
    # 점화식으로 dp 테이블 갱신
    for i in range(1, N + 1):
        for j in range(1, M + 1):
            dp[i][j] += max(dp[i - 1][j], dp[i][j - 1])
            
    print(dp[-1][-1])