본문 바로가기

알고리즘/BOJ

1463번

1463 - 1로 만들기



1. 완전 탐색을 이용해서 풀기


재귀 함수를 이용해서 모든 케이스를 다 돌려보았다.

재귀를 돌리는 중에 지금 현재의 최소값보다 큰 값이 나오면 return 해주는 방식으로 속도를 조금 빠르게 했다.


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
31
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>
using namespace std;
int ans = 987654321;
void go(int n, int cnt)
{
    if (cnt > ans)
    {
        return;
    }
    
    if (n == 1)
    {
        ans = cnt > ans ? ans : cnt;
        return;
    }
 
    if (n % 3 == 0)
    {
        go(n / 3,cnt+1);
    }
 
    if (n % 2 == 0)
    {
        go(n / 2,cnt+1);
    }
 
    go(n - 1,cnt+1);
 
    return;
 
}
int main()
{
    int N;
    cin >> N;
 
    go(N,0);
 
    cout << ans << endl;
 
    return 0;
}
cs


2. BFS를 이용해서 풀기


어떤 연산을 이용해도 연산 횟수는 1이 증가하기 때문에, 가중치가 1인 그래프라고 볼 수 있다.

그리고 이때의 연산횟수의 최솟값을 구하는 것이기 때문에 BFS로 풀 수 있었다.



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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<iostream>
#include<queue>
using namespace std;
bool check[1000001];
int dist[1000001];
int main()
{
    int n;
    cin >> n;
 
    queue<int> q;
 
    q.push(n);
    check[n] = true;
    dist[n] = 0;
 
    while (!q.empty())
    {
        int x = q.front();
        q.pop();
 
        if (x == 1)
        {
            cout << dist[x] << endl;
            break;
        }
 
 
        if (x % 3 == 0 && check[x / 3== false)
        {
            int nx = x / 3;
            q.push(nx);
            check[nx] = true;
            dist[nx] = dist[x] + 1;
        }
        if (x % 2 == 0 && check[x / 2== false)
        {
            int nx = x / 2;
            q.push(nx);
            check[nx] = true;
            dist[nx] = dist[x] + 1;
        }
        if (check[x - 1== false)
        {
            int nx = x-1;
            q.push(nx);
            check[nx] = true;
            dist[nx] = dist[x] + 1;
        }
    }
 
 
    return 0;
}
cs



3.DP를 이용해서 풀기


나는 보통 재귀로 DP를 많이 푼다. for문을 이용해서 푸는 방법도 있지만...

솔직히 DP랑 완전탐색이랑 똑같다.. 다만 memoization 이 있다는..

근데 위의 완전탐색 풀때는 n/3, n/2 , n-1 로 풀었는데

아래 코드는 그 순서로 풀면 오류가 났다 왜 그럴까...?


혹시 오류 아시는 분은 말씀 좀 해주세요...ㅠㅠ

################################################################

D[N]=go(N-1)+1을 맨 마지막 줄로 바꾸면 오류가 발생하는 거 생각해보기. 질문올리기

################################################################


<정답 코드>


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
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int D[1000001];
int go(int N)
{
    if (N == 1)
    {
        return 0;
    }
    if (D[N] != -1)
    {
        return D[N];
    }
 
    D[N] = go(N - 1+ 1;
 
    if (N % 3 == 0)
    {
        D[N] = min(D[N],go(N / 3+ 1);
    }
    if (N % 2 == 0)
    {
        D[N] = min(D[N],go(N / 2+ 1);
    }
 
    
 
    return D[N];
 
}
int main()
{
    int n;
    cin >> n;
 
    memset(D, -1sizeof(D));
    
    cout << go(n) << endl;
 
    return 0;
}
cs



<오류 코드>


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
31
32
33
34
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int D[1000001];
int go(int N)
{
    if (N == 1)
    {
        return 0;
    }
    if (D[N] != -1)
    {
        return D[N];
    }
    if (N % 3 == 0)
    {
        D[N] = go(N / 3+ 1;
    }
    if (N % 2 == 0)
    {
        D[N] = min(D[N],go(N / 2+ 1);
    }
    D[N] = min(D[N],go(N - 1+ 1);
    return D[N];
}
int main()
{
    int n;
    cin >> n;
    memset(D, -1sizeof(D));
    cout << go(n) << endl;
    return 0;
}
cs


반응형

'알고리즘 > BOJ' 카테고리의 다른 글

11727번  (0) 2017.11.14
11726번  (0) 2017.11.14
2445번  (0) 2017.11.12
10818번  (0) 2017.11.12
1924번  (0) 2017.11.12