반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. Dynamic Programming

2. DP의 메모리 절약 방법


보통은 DP또한 map과 동일한 배열 크기로 만들어 진행한다.


하지만 이 문제의 메모리 제한은 4mb이다.


int형이 4byte이고 map만해도 400020 * 4이니 1,600,080b =  1563kb = 1.5mb이다.


따라서 maxDP와 minDP를 만든다면 당연히 메모리 초과가 날 것이니 이 문제는


DP의 성질을 이용해야 한다.


DP는 이전 단계의 값을 이용하여 푸는 것이기에 애초에 첫 DP값, 두번째 DP값 등등은 필요 없어지게 된다.


단지 전 단계의 DP값만 있으면 된다.


따라서

    int maxt1, maxt2, maxt3;

    int mint1, mint2, mint3;


    int maxdp1, maxdp2, maxdp3;
    int mindp1, mindp2, mindp3;


이런식으로 12가지의 dp값만 있으면 되는데 

위의 6가지 dp값은 temp값으로 dp를 계산할 때 계속 이용되는 값이고 아래 6가지 값은 실제 dp로 이용될 값이다.


저 값들은 배열로 maxdp[3], mindp[3] 이런식으로 만들어 이용한다면 더 깔끔한 코드가 완성될 수 있다.


소스 코드 : 


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
55
56
57
58
59
60
61
#include <iostream>
#include <cstdio>
 
#define max(a,b)(a>b?a:b)
#define min(a,b)(a<b?a:b)
 
using namespace std;
 
int map[100005][4];
 
int main()
{
    int n;
    int i = 1, j = 1;
 
    int maxt1, maxt2, maxt3;
    int mint1, mint2, mint3;
 
    int maxdp1, maxdp2, maxdp3;
    int mindp1, mindp2, mindp3;
 
    scanf("%d"&n);
 
    for (i = 1; i <= n; i++)
        for (j = 1; j <= 3; j++)
            scanf("%d"&map[i][j]);
 
    maxdp1 = map[1][1];
    maxdp2 = map[1][2];
    maxdp3 = map[1][3];
 
    mindp1 = map[1][1];
    mindp2 = map[1][2];
    mindp3 = map[1][3];
 
    for (i = 2; i <= n; i++)
    {
        maxt1 = max(maxdp1, maxdp2) + map[i][1];
        maxt2 = max(max(maxdp1, maxdp2), maxdp3) + map[i][2];
        maxt3 = max(maxdp2, maxdp3) + map[i][3];
 
        mint1 = min(mindp1, mindp2) + map[i][1];
        mint2 = min(min(mindp1, mindp2), mindp3) + map[i][2];
        mint3 = min(mindp2, mindp3) + map[i][3];
 
        maxdp1 = maxt1;
        maxdp2 = maxt2;
        maxdp3 = maxt3;
 
        mindp1 = mint1;
        mindp2 = mint2;
        mindp3 = mint3;
    }
 
    printf("%d %d", max(max(maxdp1, maxdp2), maxdp3), min(min(mindp1, mindp2), mindp3));
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus









아래 코드는 메모리 초과를 발생시키는 자주 이용하던 DP 모습이다.


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
#include <iostream>
#include <cstdio>
 
#define max(a,b)(a>b?a:b)
#define min(a,b)(a<b?a:b)
 
using namespace std;
 
int map[100005][4];
int MAXDP[100005][4];
int MINDP[100005][4];
 
int main()
{
    int n;
    int i = 1, j = 1;
 
    scanf("%d"&n);
 
    for(i = 1; i <= n ; i ++)
        for(j = 1; j <= 3; j++)
            scanf("%d"&map[i][j]);
    
    MAXDP[1][1= map[1][1];
    MAXDP[1][2= map[1][2];
    MAXDP[1][3= map[1][3];
 
    MINDP[1][1= map[1][1];
    MINDP[1][2= map[1][2];
    MINDP[1][3= map[1][3];
 
    for (i = 2; i <= n; i++)
    {
        MAXDP[i][1= max(MAXDP[i - 1][1], MAXDP[i - 1][2]) + map[i][1];
        MAXDP[i][2= max(max(MAXDP[i - 1][1], MAXDP[i - 1][2]), MAXDP[i - 1][3]) + map[i][2];
        MAXDP[i][3= max(MAXDP[i - 1][2], MAXDP[i - 1][3]) + map[i][3];
 
        MINDP[i][1= min(MINDP[i - 1][1], MINDP[i - 1][2]) + map[i][1];
        MINDP[i][2= min(min(MINDP[i - 1][1], MINDP[i - 1][2]), MINDP[i - 1][3]) + map[i][2];
        MINDP[i][3= min(MINDP[i - 1][2], MINDP[i - 1][3]) + map[i][3];
    }
 
    printf("%d %d", max(max(MAXDP[n][1], MAXDP[n][2]), MAXDP[n][3]), min(min(MINDP[n][1], MINDP[n][2]), MINDP[n][3]));
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[2015번] 수들의 합 4  (0) 2017.02.20
[3078번] 좋은 친구  (1) 2017.02.16
[1644번] 소수의 연속합  (0) 2017.02.14
[1806번] 부분합  (0) 2017.02.13
[2581번] 소수  (0) 2017.02.13