[BOJ]1010架橋(Week 8,No.3)


質問する


元で都市の市長になった.この町には町を東と西に分ける大きな直線形の川が流れている.しかし元知では橋がないため、市民たちが川を渡るのに大きな不便があったため、橋を建てることにした.川沿いに橋を建てるのに適した場所をウェブサイトと言います.元で江辺をよく調べたところ、江西にはNのサイトがあり、東にはMのサイトがあることが分かった.(N ≤ M)
元は西のサイトと東のサイトを橋につなぎたいと思っています.(1つのサイトには最大1つのブリッジしか接続できません.)元ではできるだけ多くの橋を建てたいので、西のサイト数に応じて(N個)橋を建てたいです.足が重ならないと言ったら、橋を建てることができれば、足の数を計算することができます.

入力


入力された第1行は、試験例の個数Tを与える.次の行から、各テストケースについて、川の西と東に位置するサイトの個数整数N,M(0

しゅつりょく


各試験例について、所与の条件下でブリッジを構築できる数を出力する.

入力例1


3
2 2
1 5
13 29

サンプル出力1


1
5
67863915

に答える


これはmブリッジでnブリッジを選択した場合の数の問題である.
交差する橋はないので、順番は気にしません.
組み合わせて得ることができます.
しかし範囲が広すぎるので、数字が大きくなると答えが得られません.(例えば、n=28、m=29)
そこでdpテーブルを用いた.
例)n=4,m=7

  • n=1の場合、dp[1][j]=jが加わる.


  • n>=2の場合
    現在の座標の左側の値が0の場合、左側の対角線の上の値が現在の値になります.
    そうでなければ、左側の対角線の上の値+左側の値が現在の値になります.


  • 最終dpテーブル

  • 最後にdp[n][m]を返す.

    コード#コード#


    組み合わせ(失敗)

    import java.util.Scanner;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int T = sc.nextInt();
    
            if (T == 0) {
                return;
            }
    
            for (int i = 0; i < T; i++) {
                int N = sc.nextInt();
                int M = sc.nextInt();
    
                if (N == 1) {
                    System.out.println(M);
                    return;
                }
    
                long m = 1;
                for (int j = M; j > M - N; j--) {
                    m *= j;
                }
                for (int j = N; j >= 1; j--) {
                    m /= j;
                }
                
                System.out.println(m);
            }
        }
    }

    DP(成功)

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class Main {
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            int T = Integer.parseInt(br.readLine());
            for (int t = 0; t < T; t++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                int N = Integer.parseInt(st.nextToken());
                int M = Integer.parseInt(st.nextToken());
    
                // base case
                if (N == 1) {
                    System.out.println(M);
                    continue;
                }
                if (N == M) {
                    System.out.println(1);
                    continue;
                }
    
                long[][] dp = new long[31][31];
    
                for (int i = 1; i <= M; i++) {
                    dp[1][i] = i;
                }
    
                for (int i = 2; i <= N; i++) {
                    for (int j = i; j <= M; j++) {
                        dp[i][j] = dp[i - 1][j - 1];
                        if (j != i) {
                            dp[i][j] += dp[i][j - 1];
                        }
                    }
                }
                System.out.println(dp[N][M]);
            }
        }
    }