t8m8-mem8

競プロとか、学んだことを書いていきます。

SRM 398 Div1 Medium: CountPaths

問題

r×cマスのテーブル上にいくつかの特別なマスがある。この特別なマスを踏んだ回数ごとに(1,1)から(r,c)への経路数を求める。

移動は(i,j)から(i+1,j)または(i,j+1)へのみ可能で、特別なマスは与えられた順番を戻るように踏むことはできない(i番目の特別なマスを踏んだあとにj番目の特別なマスを踏むとき、i<jでないといけない)。

制約

 { \displaystyle
1{\leq} r,c {\leq}50
}

 { \displaystyle
0{\leq}特別なマスの個数{\leq}50
}

解法

DP

dp[r][c][k][n] := k番目の特別なマスを最後に踏んで、合計n個の特別なマスを踏んだ状態での(r,c)までの経路数

感想

Div1 Medにしては簡単なDPだった気がする。

import java.util.*;

public class CountPaths {

    static final int MOD = 1000007;

    public int[] difPaths(int r, int c, int[] fieldrow, int[] fieldcol) {
        int n = fieldrow.length;
        int[][] sf = new int[r][c];

        for (int i=0; i<n; i++) {
            sf[fieldrow[i]-1][fieldcol[i]-1] = i+1;
        }

        int[][][][] dp = new int[r][c][n+1][n+1];
        if (sf[0][0] == 0) dp[0][0][0][0] = 1;
        else dp[0][0][sf[0][0]][1] = 1;

        for (int i=0; i<r; i++) {
            for (int j=0; j<c; j++) {
                for (int k=0; k<=n; k++) {
                    for (int l=0; l<=n; l++) {
                        if (i+1 < r && sf[i+1][j] > k && l+1 <= n) {
                            dp[i+1][j][sf[i+1][j]][l+1] = (dp[i+1][j][sf[i+1][j]][l+1] + dp[i][j][k][l])%MOD;
                        } else if (i+1 < r && sf[i+1][j] == 0) {
                            dp[i+1][j][k][l] = (dp[i+1][j][k][l] + dp[i][j][k][l])%MOD;
                        }

                        if (j+1 < c && sf[i][j+1] > k && l+1 <= n) {
                            dp[i][j+1][sf[i][j+1]][l+1] = (dp[i][j+1][sf[i][j+1]][l+1] + dp[i][j][k][l])%MOD;
                        } else if (j+1 < c && sf[i][j+1] == 0) {
                            dp[i][j+1][k][l] = (dp[i][j+1][k][l] + dp[i][j][k][l])%MOD;
                        }
                    }
                }
            }
        }

        int[] res = new int[n+1];

        for (int i=0; i<=n; i++) {
            for (int j=0; j<=n; j++) {
                res[i] = (res[i] + dp[r-1][c-1][j][i])%MOD;
            }
        }

        return res;
    }
}
広告を非表示にする