[BOJ/Python]1520号下り坂



この問題は深さ優先探索と動的プログラミングで解決した.最初は深さ優先探索だけで近づく.簡単にdfs()関数では、現在位置よりも現在位置が小さい場合に再呼び出しし、[M-1][n-1]に達すると、グローバル変数を1つ増やす方法で実現する.テストケースの正解はよく導出されています.
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline
def dfs(y, x):
    global cnt
    dy=[0, 0, -1, 1]
    dx=[1, -1, 0, 0]
    if y==m-1 and x==n-1:
        cnt+=1
        return
    for i in range(4):
        ny=y+dy[i]
        nx=x+dx[i]
        if ny>=0 and nx>=0 and ny<m and nx<n and maps[ny][nx]<maps[y][x]:
            dfs(ny, nx)
m, n=map(int, input().split())
maps=[]
for _ in range(m):
    maps.append(list(map(int, input().split())))
cnt=0
dfs(0, 0)
print(cnt)
しかしタイムアウトが発生した.問題を探すことにより,DFS+DPを適用してこそ時間内に問題を解決できることが分かった.mとnの最値が大きすぎるからかもしれません.
そこでDFS+DP方式で解いた.dpリストでアクセス処理とカウントを同時に行いました.1は初期化を行い、dp[y][x]が-1であれば未アクセスの位置と判断してナビゲートし、-1でなければ以前にアクセスした位置であるため、そのdp[y][x]値を加算する.[M−1][n−1]に達すると、dp[y][x]に1を加算する.
DFSとDPの結合の問題に初めて接触するのに多くの時間がかかった.少し解を探した.このような問題も多く解決しなければならない.
  • dfs関数をy,xをパラメータとして宣言します.
    ->4方向の情報ペアをdy,dxリストに格納する.
    ->yがm-1、xがn-1の場合、1を返します.
    ->dp[y][x]が-1でない場合、dp[y][x]を返します.
    ->dp[y][x]を0に更新します.(オンサイトサービス)
    ->4回繰り返すiに対してfor文を回す.
    -->nyはy+dy[i]として格納される.
    -->nxをx+dx[i]として保存します.
    -->ny、nxが0以上、nyがm未満、nxがn未満、maps[ny][nx]がmaps[y][x]未満の場合、dp[y][x]にdfs(ny,nx)の戻り値を加算します.
    ->dp[y][x]が返されます.
  • mとnを入力します.
  • 地図情報を保存するリスト図を発表した.
  • メートルのforドアの回転を繰り返します.
    ->マップ入力を受け入れます.
  • dpをm*nの−1に充填した.
  • 出力
  • dfs(0,0).
  • Code

    import sys
    sys.setrecursionlimit(10**9)
    input = sys.stdin.readline
    def dfs(y, x):
        dy=[0, 0, -1, 1]
        dx=[1, -1, 0, 0]
        if y==m-1 and x==n-1:
            return 1
        if dp[y][x]!=-1:
            return dp[y][x]
        dp[y][x]=0
        for i in range(4):
            ny=y+dy[i]
            nx=x+dx[i]
            if ny>=0 and nx>=0 and ny<m and nx<n and maps[ny][nx]<maps[y][x]:
                dp[y][x]+=dfs(ny, nx)
        return dp[y][x]
    m, n=map(int, input().split())
    maps=[]
    for _ in range(m):
        maps.append(list(map(int, input().split())))
    dp=[[-1]*n for _ in range(m)]
    print(dfs(0, 0))