백준 1010번

우인·2022년 1월 15일

백준

목록 보기
1/4

1010번

👍 문제

재원이는 한 도시의 시장이 되었다. 이 도시에는 도시를 동쪽과 서쪽으로 나누는 큰 일직선 모양의 강이 흐르고 있다.
하지만 재원이는 다리가 없어서 시민들이 강을 건너는데 큰 불편을 겪고 있음을 알고 다리를 짓기로 결심하였다.
강 주변에서 다리를 짓기에 적합한 곳을 사이트라고 한다.
재원이는 강 주변을 면밀히 조사해 본 결과 강의 서쪽에는 N개의 사이트가 있고 동쪽에는 M개의 사이트가 있다는 것을 알았다. (N ≤ M)

재원이는 서쪽의 사이트와 동쪽의 사이트를 다리로 연결하려고 한다.
(이때 한 사이트에는 최대 한 개의 다리만 연결될 수 있다.)
재원이는 다리를 최대한 많이 지으려고 하기 때문에 서쪽의 사이트 개수만큼 (N개) 다리를 지으려고 한다.
다리끼리는 서로 겹쳐질 수 없다고 할 때 다리를 지을 수 있는 경우의 수를 구하는 프로그램을 작성하라.

👍 입/출력

입력 : 테스트 케이스 수인 T, T만큼의 (N,M) 쌍 입력받음
출력 : 해당 (N,M) 경우에 따라 다리를 지을 수 있는 경우의 수

👍 내 나름대로 해설??

일단 아래 코드에서 보다싶이 '동적 프로그래밍'을 사용하였다.
서쪽에 4개, 오른쪽에 7개의 사이트가 존재할 때
서쪽 맨 위 사이트를 A 사이트로 가정한다면 A가 오른쪽 7개(a,b,c,d,e,f,g)에
하나씩 연결되었을 때를 가정한다면

BCD 사이트 3개가 오른쪽 6개(A-a),5개(A-b),.....,0(A-g)개에 연결된 경우를 전부 더하면
(왼쪽 사이트 4개,오른쪽 사이트 7개)로 연결될 수 있는 가짓 수가 전부 나올 수 있다.

즉, 이를 일반화하면
dp[N][M] = dp[N-1][M-1] + ... + dp[N-1][0]
이라고 나타낼 수 있다.

N=1인 경우는 M의 수만큼 경우의 수가 나오므로 쉽게 구할 수 있고
N이 2이상일 경우에는 N-1의 결과 값에 따라 쉽게 구할 수 있으므로
동적 프로그래밍으로 해결 가능하다.

이 중 N이 M보다 큰 경우는
dp[N][M] = 0으로 되어있어 계산에 영향을 주지 않음.
전역변수로 고정된 값으로 배열선언만하고 value 지정 없을시 배열내의 모든 값은 0으로 초기화가 된다.

👍 c++ 정답 코드

#include <bits/stdc++.h>
using namespace std;

int dp[31][31];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    for (int i = 1; i <= 30; i++)
        dp[1][i] = i;

    for (int i = 2; i <= 30; i++) {
        for (int j = i; j <= 30; j++) {
	    for (int k = j - 1; k >= 1; k--) {
			    dp[i][j] += dp[i - 1][k];
		    }
	    }
    }

    int T;
    cin >> T;
    
    while (T--) {
        int n, m;
        cin >> n >> m;
        cout << dp[n][m] << "\n";
    }
    return 0;
}
profile
컴퓨터신생아

0개의 댓글