문제출처 : baekjoon online judge

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다. 아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크

www.acmicpc.net

문제의 큰 틀은 bfs를 활용하는 방법으로 접근했습니다.

bfs로 탐색하다 그 거리에 다음 후보지가 있으면 그 후보지는 que에 넣지 않고 다음 거리 탐색하기 전에 그곳을 기점ㅇ으로 다시 bfs를 실행합니다.

만약 같은 거리에 후보지가 많으면 y, x 값을 비교해 최종 후보지를 선택합니다.

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include<iostream>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
int n;
int map[22][22];
int check[22][22];
 
int que_x[400];
int que_y[400];
int que_d[400];
 
int rear = 0;
int top = 0;
 
int fx, fy;
int now = 2//
int sum = 0// 먹은 물고기 개수
 
int dir_x[4= { 0,-1,0,1 };
int dir_y[4= { -1,0,1,0 };
int dist = 0;
 
void bfs() {
    int checking = 0;
 
    while (rear < top) {
        int x = que_x[rear];
        int y = que_y[rear];
        int d = que_d[rear++];
 
        if (que_d[top - 1== d) { // 다음 거리를 탐색할 때, 이전에 이동할 수 있는 곳이 있나 확인한 후 그곳으로 이동해서 다시 bfs
            if (checking == 1) { //갈 곳이 있는지 체크
                map[fy][fx] = 0;
                sum = (sum + 1) % now;
                if (sum == 0)                
                    now++//여기까지 먹었을 때 처리
 
                top = 0;
                rear = 0;
 
                memset(check, 0sizeof(check));
                check[fy][fx] = 1;
                que_x[top] = fx;
                que_y[top] = fy;
                que_d[top++= 0// 초기화
 
                bfs(); // 다시 bfs
                return;
            }
        }
        for (int i = 0; i < 4; i++) {
            int next_x = x + dir_x[i];
            int next_y = y + dir_y[i];
            int next_d = d + 1;
 
            if (map[next_y][next_x] < now && map[next_y][next_x] > 0) { // 후보지일 때, 큐에 넣지 않고 이전 후보지와 비교
                if (checking == 0) { // 
                    fx = next_x;
                    fy = next_y;
                    dist += next_d;
                }
                else {
                    if (next_y < fy) { // 더 위에있는 후보지 선택
                        fy = next_y;
                        fx = next_x;
                    }
                    else if(next_y == fy){
                        if (next_x < fx) { //더 왼쪽에 있는 후보지 선택
                            fy = next_y;
                            fx = next_x;
                        }
                    }
                }
                que_d[top++= next_d;
                checking = 1;
            }
            if (checking == 0) {
                if (map[next_y][next_x] == 0 || map[next_y][next_x] == now) {
                    if (check[next_y][next_x] == 0) {
                        check[next_y][next_x] = 1;
 
                        que_x[top] = next_x;
                        que_y[top] = next_y;
                        que_d[top++= next_d;
                    }
                }
            }
        }
    }
}
int main() {
    memset(map, -1sizeof(map));
 
    cin >> n;
 
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> map[i][j];
 
            if (map[i][j] == 9) {
                fx = j;
                fy = i;
            }
        }
    }
    map[fy][fx] = 0;
    check[fy][fx] = 1;
    que_x[top] = fx;
    que_y[top++= fy;
    bfs();
 
    cout << dist << endl;
 
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

 

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

문제출처 : baekjoon online judge

 

14501번: 퇴사

첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.

www.acmicpc.net

이 문제는 전형적인 다이나믹프로그래밍 문제입니다.

각 날짜마다 일했을 때, 구할 수 있는 최대 이윤과 그 날 일하지 않고 다음 날 일했을 때 최대 이윤을 비교하는 방식입니다.

각 날짜마다 걸리는 시간을 고려해서, 일 할 수 없으면 0으로 설정해서 다음 날 일했을 때 이윤과 비교합니다.

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
#include<iostream>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
int cache[20];
 
int t[20];
int p[20];
 
int n;
 
int dp(int x) {
    if (x > n)
        return 0;
 
    int &ret = cache[x];
 
    if (ret != -1)
        return ret;
 
    if (x + t[x] - 1 > n)
        return ret = max(0, dp(x + 1));
 
 
    return ret = max(dp(x + 1), p[x] + dp(x + t[x]));
}
 
int main() {
    cin >> n;
 
    for (int i = 1; i <= n; i++) {
        cin >> t[i] >> p[i];
    }
 
    memset(cache, -1sizeof(cache));
 
    dp(1);
 
    int answer = 0;
 
    for (int i = 1; i <= n; i++) {
        answer = max(answer, cache[i]);
    }
 
    cout << answer << endl;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

 

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

문제출처 : baekjoon online judge

 

15685번: 드래곤 커브

첫째 줄에 드래곤 커브의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 드래곤 커브의 정보가 주어진다. 드래곤 커브의 정보는 네 정수 x, y, d, g로 이루어져 있다. x와 y는 드래곤 커브의 시작 점, d는 시작 방향, g는 세대이다. (0 ≤ x, y ≤ 100, 0 ≤ d ≤ 3, 0 ≤ g ≤ 10) 입력으로 주어지는 드래곤 커브는 격자 밖으로 벗어나지 않는다. 드래곤 커브는 서로 겹칠 수 있다. 방향은 0, 1, 2,

www.acmicpc.net

이 문제는 스택을 활용한 문제입니다.

0세대일 때의 두 점을 우선 1로 표현하고 방향을 스택에 저장합니다.

그 후, 스택의 방향을 pop하여 다음 방향을 구하고 다시 그 방향을 스택에 push하는 방식으로 문제를 해결합니다. 실제로 pop을 하지는 않고 다른 변수에 저장해서 활용합니다.

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include<iostream>
#include<algorithm>
 
using namespace std;
 
int dir_x[4= { 1,0,-1,0 };
int dir_y[4= { 0,-1,0,1 };
 
int next_dir[4= { 1,2,3,0 };
int stack_dir[1024];
int dir_top = 0;
 
int map[102][102];
 
int count(int x1, int y1, int x2, int y2) { // 네모 개수 세기
    int sum = 0;
 
    for (int i = y1; i < y2; i++) {
        for (int j = x1; j < x2; j++) {
            if (map[i][j] == 1 && map[i + 1][j + 1== 1 && map[i + 1][j] == 1 && map[i][j + 1== 1
                sum++;
        }
    }
 
    return sum;
}
int main() {
    int n;
 
    cin >> n;
 
    int min_x = 101, min_y = 101, max_x = -1, max_y = -1// 탐색해야될 범위를 저장
 
    for (int i = 0; i < n; i++) {
        int x, y, d, g;
 
        cin >> x >> y >> d >> g;
 
        min_x = min(x, min_x);
        min_y = min(y, min_y);
        max_x = max(x, max_x);
        max_y = max(y, max_y);
 
        map[y][x] = 1// 첫번째 점
 
        stack_dir[dir_top++= d;
 
        x = x + dir_x[d];
        y = y + dir_y[d];
 
        min_x = min(x, min_x);
        min_y = min(y, min_y);
        max_x = max(x, max_x);
        max_y = max(y, max_y);
 
        map[y][x] = 1// 두번째 점
        
        for (int i = 0; i < g; i++) {
            int tmp = dir_top - 1;
            for (int j = tmp; j >= 0; j--) {
                d = next_dir[stack_dir[j]]; // pop
 
                x = x + dir_x[d];
                y = y + dir_y[d];
 
                min_x = min(x, min_x);
                min_y = min(y, min_y);
                max_x = max(x, max_x);
                max_y = max(y, max_y);
 
                map[y][x] = 1;
 
                stack_dir[dir_top++= d; // push
            }
        }
        dir_top = 0;
    }
    int result = count(min_x, min_y, max_x, max_y);
 
    cout << result << endl;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

 

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

문제출처 : baekjoon online judge

 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선이 같은 위치를 갖는다. 아래 그림은 N = 5, H = 6 인 경우의 그림이고, 가로선은 없다. 초록선은 세로선을 나타내고, 초록선과 점선이 교차하는 점은 가로선을 놓을 수 있는 점이다. 가로선은 인접한 두 세로선을 연결해야 한다. 단, 두 가로선이 연속하거나 서로

www.acmicpc.net

이 문제는 완전탐색 문제입니다.

탐색해야 될 경우의 수도 많지 않고 깊이도 깊지 않기 때문에 DFS를 활용한 완전탐색을 통해 문제를 해결했습니다.

사다리를 어떻게 표현하는 지도 중요한데 저는 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
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include<iostream>
 
using namespace std;
int n, m, h;
int ladder[32][12];
 
int blank_x[300];
int blank_y[300];
int blank_top = 0;
 
int minimum = 4;
 
int search(int x) { // x열 사다리 타기
    int goal = x;
 
    for (int i = 1; i <= h; i++) {
        int tmp = x;
 
        if (ladder[i][tmp] == 1)
            x++;
        else if (ladder[i][tmp - 1== 1)
            x--;
    }
 
    if (x == goal) {
        return 1;
    }
 
    return 0;
}
int simul_all() {
    for (int i = 1; i <= n; i++) {
        if (search(i) == 0) {
            return 0;
        }
    }
    return 1;
}
int side_check(int x, int y) { // 양 옆 사다리 체크
    if (ladder[y][x - 1== 1 || ladder[y][x + 1== 1)
        return 0;
 
    return 1;
}
 
void dfs(int start, int sum) {
    if (sum >= minimum) // 가지치기 최소 사다리 개수보다 많으면 탐색 X
        return;
    else{
        for (int i = start; i < blank_top; i++) {
            int x = blank_x[i];
            int y = blank_y[i];
 
            if (side_check(x, y) == 1) {
                ladder[y][x] = 1;
 
                if (simul_all() == 1) {
                    minimum = sum;
                    ladder[y][x] = 0;
                    return;
                }
                else {
                    dfs(i + 1, sum + 1);
                    ladder[y][x] = 0;
                }
            }
        }
    }
 
}
int main() {
    cin >> n >> m >> h;
 
    for (int i = 0; i < m; i++) {
        int a, b;
 
        cin >> a >> b;
 
        ladder[a][b] = 1;
    }
 
    if (simul_all() == 1) { // 사다리를 추가하지 않은 상태를 탐색
        cout << "0" << endl;
        return 0;
    }
 
    for (int i = 1; i <= h; i++) { // 빈공간(탐색구간)을 스택에 쌓음
        for (int j = 1; j < n; j++) {
            if (ladder[i][j] == 0) {
                if (side_check(j, i) == 1) { // 양 옆에 사다리가 있는 지 판단
                    blank_x[blank_top] = j;
                    blank_y[blank_top++= i;
                }
            }
        }
    }
 
    dfs(01);
 
    if (minimum == 4)
        cout << "-1" << endl;
    else
        cout << minimum << endl;
 
}
" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

열의 범위를 1부터 n까지 설정하고 ladder를 표현하는 2차원 배열의 범위는 0부터 n+1이상 까지 생성해줬기 때문에 따로 x열을 사다리 태울 때, 범위를 체크할 필요가 없었습니다.

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

문제 출처 : SW Expert

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

Q. 사칙 연산을 이진 트리로 표현할 때, 연산의 결과를 계산하는 프로그램을 작성하시오. 

단, 정점에 대한 정보는 입력으로 주어진다.

 

문제에서 이진 트리로 표현한다고 했지만 배열을 이용하면 간단하게 풀 수 있는 문제입니다.

이 문제는 방법은 중위순회를 이용해 해결하면 되죠. 저는 입력을 처리하는 데에서 약간 애를 먹었네요.

아예 하나의 스트링으로 받아서 케이스를 구분하는 방향으로 입력을 처리했습니다.

정점의 값이 연산일 때, 자식 정점 번호도 주어지는 데, 저는 자식 번호는 무조건 *2, *2 + 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include<iostream>
#include<cstring>
#include<string>
 
using namespace std;
 
string s[1001];
 
long long inorder(int num) {
    if (s[num][1> '9' || s[num][1< '0') { // 연산일 때,
        int num1 = 0//자식노드 1
        int num2 = 0//자식노드 2
        int i = 3//자식노드가 주어지는 시작 인덱스
 
        while (1) {
            if (s[num][i] == ' ') {
                break;
            }
            num1 *= 10;
            num1 += s[num][i] - '0';
            i++;
        }
        i++;
        while (s[num].size() > i ) {
            if (s[num][i] == ' ') {
                break;
            }
            num2 *= 10;
            num2 += s[num][i] - '0';
            i++;
        }
        if (s[num][1== '+') {
            return inorder(num1) + inorder(num2); // + 중위순회
        }
        else if (s[num][1== '-') {
            return inorder(num1) - inorder(num2); // - 중위순회
 
        }
        else if (s[num][1== '*') {
            return inorder(num1) * inorder(num2); // * 중위순회
 
        }
        else if (s[num][1== '/') {
            return inorder(num1) / inorder(num2); /// 중위순회
 
        }
    }
    else {
        int size = s[num].size();
        long long sum = 0;
 
        for (int i = 1; i < size; i++) {
            sum *= 10;
            sum += s[num][i] - '0';
        }
        return sum;
    }
    
}
int main() {
    int T = 10;
    int idx = 0;
 
    while (idx++ < T) {
        int n;
 
        cin >> n;
 
        for (int i = 0; i < n; i++) {
            int num;
            string c;
 
            cin >> num;
            getline(cin, c);
 
            s[num] = c;
        }
        /*for (int i = 1; i <= n; i++) {
            cout << s[i][1] << endl;
        }*/
        long long result = inorder(1);
 
        cout << "#" << idx << " " << result << endl;
 
    }
}
 

 

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

문제 출처 : SW Expert

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

Q. 출발지와 도착지가 주어졌을 때, 출발지 부터 도착지 까지 경로가 있는 지 판단하는 프로그램을 작성하시오.

단, 지도는 100X100 행렬 형태이며, 출발지는 2, 도착지는 3, 경로는 0, 벽은 1로 표현된다.

 

전형적인 완전탐색 문제에요. 탐색을 진행하다 도착지에 도달하면 탐색을 끝내는 방향으로 문제를 해결했습니다.

bfs로도 해결할 수 있지만 저는 dfs로 해결했습니다.

너무 기본적인 해결방법이라 더 이상의 설명보다 코드를 보여드리는게 나을 꺼 같습니다. 헤헤

 

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
62
63
64
65
66
67
68
69
70
71
#include<iostream>
#include<cstring>
#include<string>
 
using namespace std;
 
int map[102][102];
int check[102][102];
 
int dir_x[4= { 0,1,0,-1 };
int dir_y[4= { 1,0,-1,0 };
 
int result = 0;
 
void dfs(int x, int y) {
    int chance = 0;
    check[y][x] = 1// 중복 탐색 방지
    for (int i = 0; i < 4; i++) {
 
        int next_x = x + dir_x[i];
        int next_y = y + dir_y[i];
 
        if (map[next_y][next_x] == 3) {
            result = 1;
        }
        else if (map[next_y][next_x] == 0 && check[next_y][next_x] == 0 && result == 0) { // result를 검사, 도착지에 방문하면 탐색 종료
            
            dfs(next_x, next_y);
        }
    }
}
int main() {
    int T = 10;
    int idx = 0;
 
    while (idx++ < T) {
        int n;
 
        cin >> n;
 
        memset(map, -1sizeof(map));
 
        string s;
 
        int start_x = 0;
        int start_y = 0;
 
        for (int i = 1; i < 101; i++) {
            cin >> s;
 
            for (int j = 1; j < 101; j++) {
                map[i][j] = s[j - 1- '0';
                
                if (map[i][j] == 2) {
                    start_y = i;
                    start_x = j;
                }
            }
        }
    
        dfs(start_x, start_y);
 
        if (result == 1)
            cout << "#" << idx << " 1" << endl;
        else 
            cout << "#" << idx << " 0" << endl;
 
        result = 0;
        memset(check, 0sizeof(check));
    }
}
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
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<iostream>
#include<string>
#include<cstring>
 
using namespace std;
 
char operation[1000];
int top = 0;
 
int main() {
    string s;
    string postfix;
 
    cin >> s;
 
    int size = s.size();
 
    for (int i = 0; i < size; i++) {
        char c = s[i];
        if (c <= '9' && c >= '0')
            postfix += c;
        else if (c == '+' || c == '-') {
            if (top > 0) {
                char p_operation = operation[--top];
 
                if(p_operation == '(') {
                    operation[top++= p_operation;
                    operation[top++= c;
                }
 
                else {
                    postfix += p_operation;
                    operation[top++= c;
                }
            }
            else {
                operation[top++= c;
            }
        }
        else if (c == '*' || c == '/') {
            if (top > 0) {
                char p_operation = operation[--top];
 
                if (p_operation == '*' || p_operation == '/') {
                    postfix += p_operation;
                    operation[top++= c;
                }
                else{
                    operation[top++= p_operation;
                    operation[top++= c;
                }
            }
            else {
                operation[top++= c;
            }
        }
        else if (c == '(') {
            operation[top++= c;
        }
        else if (c == ')') {
            while (1) {
                char p = operation[--top];
                if (p == '(')
                    break;
                else
                    postfix += p;
            }
        }
    }
    while (--top >= 0) { // 마지막에 남은 연산자들 넣기
        postfix += operation[top];
    }
 
    cout << postfix << endl;
 
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
h

 

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

문제 출처 : SW Expert

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

 

Q. 덧셈, 곱셈, 괄호 연산으로 구성된 식이 주어졌을 때, 후위식으로 변환하여 계산하는 프로그램을 작성하시오.

이 문제는 저번 문제에서 괄호 연산이 추가된 문제에요. 따라서 기본 방향은 같고 괄호 연산에 대한 케이스를 추가하는 방향으로 문제를 해결했습니다.

추가된 케이스는 1. 기본 괄호 연산(중첩 포함) 2. 곱하기 연산 뒤에 괄호가 나오는 것, 이 두 가지로 설정했습니다.

 

1. 기본 괄호 연산 해결 방향

기존 문제의 더하기 연산은 더하기 연산의 개수 만큼 후위식으로 변환할 때, 마지막에 추가하는 방향이었죠. 

괄호 안에 더하기 연산도 같은 방향으로 생각했어요. 그 괄호에 해당하는 더하기 연산을 괄호가 끝날 때, 추가해주는 것이죠. 

중첩괄호 일때, 따로 케이스를 나누지 않더라도 위의 방법으로 해결가능합니다.

 

2. 곱하기 연산 뒤에 괄호

이 케이스는 괄호마다 곱하기 연산의 피연산자인지 구별할 수 있는 check flag를 두었습니다.

check flag가 1이면 "* (숫자1 + 숫자2)" => "숫자1숫자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
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
 
using namespace std;
 
string s;
 
int num[10000];
int top = 0;
 
int pnum[10000]; // 괄호에 해당하는 더하기 연산의 개수
int mcheck[1000]; // 곱하기 연사의 피연산자로 괄호이면 1, 숫자면 0
int ptop = -1// 현재 괄호의 번호
 
int main() {
    int T = 10;
    int idx = 0;
 
    while (idx++ < T) {
        int n;
 
        cin >> n;
        cin >> s;
 
        string postfix;
 
        int plus_num = 0// 본문의 더하기 연산의 개수
        int check = 0// 곱셈 연산 뒤 괄호일 때를 판단하는 flag
 
        for (int i = 0; i < n; i++) {
            char c = s[i];
 
            if (c >= '0' && c <= '9') { // 숫자일 때, 후위식에 추가
                postfix += c;
            }
 
            else if (c == '+' && check == 0) { // 더하기 일 때, 본문의 더하기 연산 개수 +1
                plus_num++;
            }
 
            else if (c == '+' && check == 1) { // 괄호 안일 때, 그 괄호에 해당하는 더하기 연산 개수 +1
                pnum[ptop]++;
            }
            else if (c == '*') {
                if (s[++i] != '(') { // 곱하기 연산 뒤에 피연산자가 숫자이면 피연산자 먼저 후위식에 추가한다음 곱하기 연산 추가
                    postfix += s[i];
                    postfix += '*';
                }
                else { // 곱하기 연산 뒤에 괄호 일때,
                    check = 1//flag 1로 바꿔줌
                    ptop++// 괄호 번호  
                    mcheck[ptop] = 1
                }
            }
            else if (c == '(') {
                check = 1// 괄호 flag 1로 바꿔줌
                ptop++// 괄호 번호 
            }
            else if (c == ')') {
                if (ptop == 0)
                    check = 0;
                for (int j = 0; j < pnum[ptop]; j++) {
                    postfix += '+';
                }
                pnum[ptop] = 0;
                if (mcheck[ptop] == 1) { // 곱하기 연산의 피연산자로 괄호가 나오면, 후위식으로 변환할 때 나중에 곱하기 연산을 더해줘야함
                    postfix += '*';
                    mcheck[ptop] = 0// 초기화
                }
                ptop--// 괄호 리셋
            }
        }
        for (int i = 0; i < plus_num; i++) {
            postfix += '+';
        }
 
        for (int i = 0; i < postfix.size(); i++) { // 후위연산 계산, stack 이용
            char c = postfix[i];
 
            if (c >= '0' && c <= '9') {
                num[top++= c - '0';
            }
            else if (c == '+') {
                int a = num[--top];
                int b = num[--top];
                int cal = a + b;
                num[top++= cal;
            }
            else if (c == '*') {
                int a = num[--top];
                int b = num[--top];
                int cal = a * b;
                num[top++= cal;
            }
        }
        cout << "#" << idx << " " << num[0<< endl;
        
        ptop = -1//초기화
        top = 0;
        memset(mcheck, 0sizeof(mcheck));
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter

 

의견이 있으시거나 수정해야할 부분이 있으면 편하게 공유 부탁드립니다!

+ Recent posts