티스토리 뷰
백준 온라인 저지(BOJ) 9184번 신나는 함수 실행
https://www.acmicpc.net/problem/9184
9184번: 신나는 함수 실행
입력은 세 정수 a, b, c로 이루어져 있으며, 한 줄에 하나씩 주어진다. 입력의 마지막은 -1 -1 -1로 나타내며, 세 정수가 모두 -1인 경우는 입력의 마지막을 제외하면 없다.
www.acmicpc.net
* 사용언어 : C언어, C++
1. 문제
문제에 주어진 w(a, b, c)를 구현하여 출력하는 프로그램을 작성
2. 풀이
문제에 w(a, b, c) 함수가 주어져있지만 그 방식 그대로 구현하면 시간 초과가 발생합니다.
시간 초과가 발생하지 않도록 불필요한 반복을 줄이려면 동적 계획법을 사용하면 됩니다.
동적 계획법은 용어 자체가 직관적이지 않은데, 기억하며 풀기(memoization)로 바꾸어 생각하면 보다 이해가 쉽습니다.
메모이제이션은 동일한 계산을 반복해야 할 때 이전에 계산한 값을 메모리에 저장하여 활용하는 기법입니다.
동적 계획법을 활용하면 메모이제이션을 활용하기 때문에 수행 시간을 큰 폭으로 줄일 수 있습니다.
(cf. 동적 계획법과 메모이제이션은 동의어가 아닙니다. 메모이제이션이 더욱 넓은 범위의 단어입니다.)
우선 dp[101][101][101]이라는 배열을 선언해두고 w(a, b, c)를 계산할 때마다 dp[a][b][c]에 값이 있는지를 확인합니다.
값이 있으면 그대로 return하고, 없으면 주어진대로 w를 계산하여 dp[a][b][c]에 저장한 뒤 그 값을 return 하면 됩니다.
a, b, c 값은 반복 횟수만 정하기 때문에 (-50, 50)의 범위에 +50을 해서 (0, 100)으로 보고 풀었습니다.
그 외 풀이는 단순하니 아래 코드로 설명 대체하겠습니다.
사실 동적 계획법을 학습하면서 알고리즘을 코드로 구현할 수 있게 되는 것 자체는 별로 의미가 없습니다.
하지만 추후 구동 시간을 줄여야하는 문제에서 활용할 만한 기법을 익힌다는 점은 상당히 큰 의미가 있는 것 같습니다.
예를 들어 특정 변수를 반복해서 연산해야 한다면 미리 한 번 해서 저장해둔 후 가져다 쓰거나
LUT(Look Up Table)을 선언해두고 처음 한 번만 계산한 후 계속 가져다가 쓰는 방식으로 활용할 수 있습니다.
dp 뿐 아니라 모든 알고리즘이 문제 해결을 위한 방법론을 배우는 것이니
원리를 이해한 후 반복 숙달하면서 방법론을 익혀두면 다양한 형태로 활용할 수 있습니다.
3. 코드
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
/*
9184_신나는 함수 실행
5140KB 12ms
*/
#include <cstdio>
const int LM = 101;
int dp[LM][LM][LM], a, b, c;
int w(int a, int b, int c) {
if (dp[a][b][c] == 0) {
if (a <= 50 || b <= 50 || c <= 50) dp[a][b][c] = 1;
else if (a > 70 || b > 70 || c > 70) dp[a][b][c] = w(70, 70, 70);
else if (a < b && b < c) dp[a][b][c] = w(a, b, c - 1) + w(a, b - 1, c - 1) - w(a, b - 1, c);
else dp[a][b][c] = w(a - 1, b, c) + w(a - 1, b - 1, c) + w(a - 1, b, c - 1) - w(a - 1, b - 1, c - 1);
}
return dp[a][b][c];
}
int main() {
#ifdef _WIN32
freopen("input.txt", "r", stdin);
#endif // _WIN32
while (1) {
scanf("%d %d %d", &a, &b, &c);
if (a == -1 && b == -1 && c == -1) break;
printf("w(%d, %d, %d) = %d\n", a, b, c, w(a + 50, b + 50, c + 50));
}
return 0;
}
'개발자 > 문제풀이 (C언어)' 카테고리의 다른 글
[백준/BOJ] 9461번 파도반 수열 (C/C++) (0) | 2024.02.26 |
---|---|
[백준/BOJ] 1904번 01타일 (C/C++) (0) | 2024.02.25 |
[백준/BOJ] 24416번 알고리즘 수업 - 피보나치 수 1 (C/C++) (0) | 2024.02.24 |
[백준/BOJ] 14889번 스타트와 링크 (C/C++) (0) | 2024.02.22 |
[백준/BOJ] 14888번 연산자 끼워넣기 (C/C++) (0) | 2024.02.22 |
- Total
- Today
- Yesterday
- 나의첫죽음학수업
- 당신도느리게나이들수있습니다
- 최재천의공부
- 센터독서클럽
- 알고리즘
- 긴 자리 덧셈 뺄셈
- 쿠프마케팅
- 세상을 읽는 새로운 언어 빅데이터
- AdSendse
- 긴 자리 곱셈
- 인간본성불패의법칙
- 여가포인트
- 유연함의힘
- 정올
- 독서감상평
- 관계가상처가되기전에
- 삼성전자
- 독서 감상평
- 영화감상평
- JUNGOL
- 동탄에듀센터2
- 나는늘잘해야한다고생각한다
- 자료구조
- 동탄에듀센터
- 자동차보험
- 문현공
- 안전운전특약
- 시대예보
- 호암의마지막꿈
- 정세현의통찰
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |