From a892cfe6cdc460bb0f3d4d371e5251c6aa37913f Mon Sep 17 00:00:00 2001 From: Subeen Date: Tue, 5 Apr 2022 23:14:10 +0900 Subject: [PATCH] =?UTF-8?q?[=EB=8F=99=EC=A0=81=20=EA=B3=84=ED=9A=8D?= =?UTF-8?q?=EB=B2=95]=204=EC=9B=94=205=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../11727_sample.cpp" | 52 +++++++++++++++++++ .../9084_sample.cpp" | 46 ++++++++++++++++ .../9095_sample.cpp" | 49 +++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 "[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/11727_sample.cpp" create mode 100644 "[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9084_sample.cpp" create mode 100644 "[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9095_sample.cpp" diff --git "a/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/11727_sample.cpp" "b/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/11727_sample.cpp" new file mode 100644 index 0000000..2b74ef4 --- /dev/null +++ "b/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/11727_sample.cpp" @@ -0,0 +1,52 @@ +#include +#include + +using namespace std; +const int MOD = 10007; // 상수 MOD = 10007, 10007로 나눈 나머지를 출력하기 위함 + +// fillTile(n) 함수 +int fillTile(int n) { // n: 정수, 2*n + vector dp(n + 1, 0); // vector dp, 크기는 n+1, 0으로 초기화 + + if (n == 1) { // 인덱스 에러 안나도록 n이 1일 경우 바로 리턴 + return 1; // n=1이면 리턴 1 + } + + // 너비 1, 2인 타일 채우는 경우의 수 미리 초기화 + dp[1] = 1; // n=1 -> 1 + dp[2] = 3; // n=2 -> 3 + + // n>= 3인 경우 + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + 2 * dp[i - 2]; // 연산 + dp[i] %= MOD; // 구하는 과정에서 int 범위 초과할 수 있으므로 마지막에 한 번이 아니라 중간 중간 모듈러 연산을 해줘야 함 + } + return dp[n]; // 리턴 dp[n] +} + +/** + * 너비를 인덱스로 써서 n까지의 너비를 채우는 방법의 수를 저장하자! + * + * 우선, 너비 1은 2(높이)x1(너비) 타일로 채우는 경우밖에 없음 + * 너비 2는 1x2 2개와 2x2 1개 총 2 경우 + 너비 1에 2x1 타일을 더한 1 경우 -> 3 경우 + * + * 그 후, 너비 3부터는 각각 너비 1, 2만큼을 뺀 타일에서 1, 2 너비 타일을 각각 더하는 경우를 생각해주자 + * 이때, 중복 경우의 수가 생기지 않도록 너비 2의 경우에서 1에서 더한 경우는 빼줌 + * -> dp[n] = (너비 1인 타일 채우는 경우의 수 = 1) * dp[n - 1] + * + (너비 2인 타일 채우는 경우의 수 = 2) * dp[n - 2] + * + * -> dp[n] = 1 * dp[n - 1] + 2 * dp[n - 2] (n >= 3) + * + * !주의! 모듈러 연산 해야함 + */ + +int main() { + int n; // 정수 n, 2*n의 n + + // 입력 + cin >> n; // 입력 받은 정수를 n에 저장 + + // 연산 & 출력 + cout << fillTile(n); // fillTile(n) 함수 호출 + return 0; +} \ No newline at end of file diff --git "a/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9084_sample.cpp" "b/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9084_sample.cpp" new file mode 100644 index 0000000..5f329e2 --- /dev/null +++ "b/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9084_sample.cpp" @@ -0,0 +1,46 @@ +#include +#include + +using namespace std; + +// kanpsack() 함수 +int knapsack(int n, int m, vector &coin) { // n: 동전의 가지 수, m: 만들 금액, coin: 동전 각 금액 + vector dp(m + 1, 0); // vector dp(주어진 동전을 이용하여 조건 금액을 만드는 경우의 수), 크기는 m+1, 0으로 초기화 + + dp[0] = 1; // 0원을 만드는 경우의 수 1 + + for (int i = 0; i < n; i++) { + for (int j = coin[i]; j <= m; j++) { // j: 동전 종류를 나타내기 위함, 만들어야 하는 금액인 m까지 반복 + dp[j] += dp[j - coin[i]]; // 해당 동전을 사용하기 전 경우의 수와 현재 경우의 수를 더함 + } + } + return dp[m]; // m원을 만드는 경우의 수 리턴 +} + +/** + * dp[i] = 주어진 동전 종류를 사용해서 i원을 만드는 경우의 수 + * + * dp[0] = 1 을 넣고 시작 (0원을 만드는 경우의 수 1로 생각) + * 각 동전마다 해당 동전부터 만들어야 하는 금액(m)까지 돌리면서 해당 동전을 사용하기 전 금액의 경우의 수와 현재 경우의 수를 더함 + * 해당 동전 사용하기 전 금액의 경우의 수가 0이면 금액을 만들 수 없는 경우이지만, 어차피 더해도 값 변화는 없으므로 따로 고려하지 않음 + */ + +int main() { + int t, n, m; // t: 테스트케이스 개수, n: 동전의 가지 수, m: n가지 동전으로 만들어야 할 금액 + + // 입력 + cin >> t; // 테스트케이스 저장 + while (t--) { // 테스트케이스 개수 동안 + cin >> n; // 동전의 가지 수 n 저장 + vector coin(n, 0); // vector coin(n가지 동전의 각 금액을 저장), 크기는 n, 0으로 초기화 + // n가지 동전의 각 금액 저장 (오름차순 배열) + for (int i = 0; i < n; i++) { + cin >> coin[i]; // 금액 저장 + } + cin >> m; // 만들어야 할 금액 m 저장 + + // 연산 & 출력 + cout << knapsack(n, m, coin) << '\n'; // knapsack() 함수 호출 + } + return 0; +} \ No newline at end of file diff --git "a/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9095_sample.cpp" "b/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9095_sample.cpp" new file mode 100644 index 0000000..e3814bb --- /dev/null +++ "b/[\353\217\231\354\240\201\352\263\204\355\232\215\353\262\225] 4\354\233\224 5\354\235\274/9095_sample.cpp" @@ -0,0 +1,49 @@ +#include +#include + +using namespace std; +const int MAX = 10; // 상수 10, 정수 n의 max 값 + +// bottom-up 방식 dp 배열 채우기 +// n=1 -> 1가지, n=2 -> 2가지 따로 작성 +vector numberOfAllCases() { // 함수 numberOfAllCases(), 벡터 반환 + vector dp(MAX + 1, 0); // vector dp, 크기는 11(MAX+1), 0으로 초기화 + + dp[0] = dp[1] = 1; // 인덱스가 0(더미 인덱스), 1인 dp(n=1인 경우)는 1 + dp[2] = 2; // 인덱스가 2인 dp(n=2인 경우)는 2로 + // n>= 3인 경우 + for (int i = 3; i <= MAX; i++) { + dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]; // 찾은 규칙 연산, 0으로 초기화 되어 있던 dp 값 업데이트 + } + return dp; // dp 리턴 +} + +/** + * [bottom-up 접근] + * 각 수를 인덱스로 써서 정수 n까지 1, 2, 3의 합으로 나타내는 방법의 수를 저장하자! + * + * 우선 3까지 1, 2, 3의 합으로 나타내는 방법의 수 초기화 함 + * 해당 인덱스에서 -1, -2, -3 한 인덱스에 +1, +2, +3을 해줬다고 생각하면 됨 + * + * -> dp[n] = dp[n - 1] + dp[n - 2] + dp[n - 3] (n >= 3) + * + * 해당 풀이는 인덱스 관리를 편하게 하기 위해 0을 더미 인덱스로 줘서 인덱스 3부터 연산 + * 테스트케이스로 입력이 들어오고, 입력 범위가 11로 작기 때문에 미리 dp 배열 채우고 시작하는 것이 더 효율적 + */ + +int main() { + int t, n; // t: 테스트 케이스의 개수, n: 정수 + + // 미리 dp 채우기 + vector dp = numberOfAllCases(); // 함수 numberOfAllCases() 호출, 리턴 값 vector dp에 저장 + + // 입력 + cin >> t; // 입력 받은 테스트케이스 수 저장 + while (t--) { // t개 동안 + cin >> n; // 입력 받은 정수 값 n에 저장 + + // 출력 + cout << dp[n] << '\n'; // 인덱스 n에 해당하는 dp 값 출력 + } + return 0; +} \ No newline at end of file