백준 알고리즘 단계별로 풀어보기/시간 복잡도

백준 알고리즘 24313번 알고리즘 수업 - 점근적 표기 1 (C++/C언어)

MNMNWVWV 2023. 3. 26. 13:48
728x90
반응형
실버Ⅳ

 

https://www.acmicpc.net/problem/24313

 

24313번: 알고리즘 수업 - 점근적 표기 1

f(n) = 7n + 7, g(n) = n, c = 8, n0 = 1이다. f(1) = 14, c × g(1) = 8이므로 O(n) 정의를 만족하지 못한다.

www.acmicpc.net

 

 

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
1 초 512 MB 3684 1168 1021 31.464%

 

문제

 

오늘도 서준이는 점근적 표기 수업 조교를 하고 있다. 아빠가 수업한 내용을 학생들이 잘 이해했는지 문제를 통해서 확인해보자.

알고리즘의 소요 시간을 나타내는 O-표기법(빅-오)을 다음과 같이 정의하자.

O(g(n)) = {f(n) | 모든 n ≥ n0에 대하여 f(n) ≤ c × g(n)인 양의 상수 c와 n0가 존재한다}

이 정의는 실제 O-표기법(https://en.wikipedia.org/wiki/Big_O_notation)과 다를 수 있다.

함수 f(n) = a1n + a0, 양의 정수 c, n0가 주어질 경우 O(n) 정의를 만족하는지 알아보자.

입력

첫째 줄에 함수 f(n)을 나타내는 정수 a1, a0가 주어진다. (0 ≤ |ai| ≤ 100)

다음 줄에 양의 정수 c가 주어진다. (1 ≤ c ≤ 100)

다음 줄에 양의 정수 n0가 주어진다. (1 ≤ n0 ≤ 100)

출력

f(n), c, n0가 O(n) 정의를 만족하면 1, 아니면 0을 출력한다.

예제 입력 1

7 7
8
1

예제 출력 1 

0

f(n) = 7+ 7, g(n) = nc = 8, n0 = 1이다. f(1) = 14, c × g(1) = 8이므로 O(n) 정의를 만족하지 못한다.

예제 입력 2

7 7
8
10

예제 출력 2

1

f(n) = 7+ 7, g(n) = nc = 8, n0 = 10이다. 모든 n ≥ 10에 대하여 7+ 7 ≤ 8이므로 O(n) 정의를 만족한다.

 

풀이 방법
반응형

우선 이 문제는 입력값 a1, a0, c, n0를 입력받았을 때 n0보다 크거나 같은 n에 대하여 모든 n이

f(n) ≤ c × g(n)

*f(n) = a1 x n + a0
*g(n) = c x n

이 식을 만족하는지를 판단하는 문제입니다.

 

여기서 n은 무조건 n0보다 큰 값이므로 다음과 같이 식을 코드로 작성할 수 있습니다.

a1 * n0 + a0 <= c * n0

하지만 코드 내의 식을 단순히 이렇게만 작성한다면 91%에서 '틀렸습니다' 가 뜰 것입니다.

그 이유는 a0에 음의 정수 즉, 마이너스(-) 값이 들어간 경우가 있을 수 있기 때문입니다.

 

입력값이 a1 = 4, a0 = -3, c = 3, n0 = 1인 경우 즉,

4n - 3 ≤ 3n (n ≥ 1)

다음과 같이 식이 작성될 경우 n=1이라면 부등식의 좌항은 1, 우항은 3이 되기 때문에 O(n)의 정의를 만족하여 1을 출력하겠지만, 사실은 n=7일 때 좌항은 25, 우항은 21이 되기 때문에 O(n)의 정의를 만족하지 못하여 0을 출력해야 합니다.

 

그렇다면 입력값이 a1 = -1, a0 = 15, c = 8, n0 = 1인 경우처럼 a0이 음의 정수가 아닌, a1이 음의 정수가 되는 경우는 어떨까요?

-n+15 ≤ 8n (n ≥ 1)

 

이 경우 다음과 같인 부등식이 만들어 지고,  n=1일 때 부등식의 좌항은 14, 우항은 8이 되어 O(n)의 정의를 만족하지 못하지만, n=5 일때 좌항은 10, 우항은 40으로 O(n)의 정의를 만족하게 됩니다.

하지만, 이 경우 처음부터 O(n)의 정의를 만족하지 못한다는 사실을 알게 되므로, 올바른 답이 출력됩니다.

 

즉, a1이 음의 정수 일때는 예외처리를 해주지 않아도 되지만, a0가 음의 정수 일때는 예외처리를 해주어야 한다는 사실을 알 수 있습니다.

따라서, 부등식 양변의 n의 차수(a1의 값과 c의 값)의 관계가 a0가 음수일 때 a1 ≤ c가 성립해야 함을 알 수 있습니다. 또한, a0가 양수일 때도 a1의 값이 c의 값보다 크다면 그 결과는 무조건 0이 되므로, 

if (a1 * n0 + a0 <= c * n0 && a1 <= c)

이와 같이 코드를 작성할 수 있음을 알 수 있습니다.

 

내 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
using namespace std;
/*
    C언어의 경우 cin은 scanf로, cout은 printf로 바꾸어 코드를 작성하면 된다.
*/
int main() {
 
    int a1, a0;
    cin >> a1 >> a0;
 
    int c;
    cin >> c;
 
    int n0;
    cin >> n0;
 
    if (a1 * n0 + a0 <= c * n0 && a1 <= c)
        cout << 1 << endl;
    else
        cout << 0 << endl;
 
    return 0;
}
cs

 

코드설명

a1, a0, c, n0를 차례로 입력받고, 

a1 * n0 + a0 <= c * n0 && a1 <= c

이 조건을 만족하면 1, 만족하지 않으면 0을 출력하는 코드입니다.

728x90
반응형