www.acmicpc.net/problem/2331

 

2331번: 반복수열

첫째 줄에 반복되는 부분을 제외했을 때, 수열에 남게 되는 수들의 개수를 출력한다.

www.acmicpc.net

D[1] = A

D[n] = D[n - 1]의 각 자리의 숫자를 M번 곱한 수(각 자리마다 ^M)들의 합입니다.

 

전 재귀를 돌려가면서 현재 숫자와 수열의 갯수를 유지하였습니다.

일의자리부터 pow(tmp, M)한 값을 next에 차례대로 더해줍니다.

next가 set에 있는 값이면 cyclestart에 next를 넣어주고 리턴합니다.

(예외처리로 D[n] = D[n - 1] 즉, 자신 다음이 자신일 경우가 있어 처리해주었습니다.)

 

재귀를 빠져나오면서 num == cyclestart이면 ans에 cnt - 1을 넣어주어 출력하였습니다.

 

 

[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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <set>
#include <cmath>
using namespace std;
 
set<int> s;
int N, M, cyclestart, ans;
 
void func(int num, int cnt) {
    s.insert(num);
 
    int n = num;
    int next = 0;
    while (1) {
        int tmp = n % 10;
        tmp = pow(tmp, M);
        next += tmp;
        n /= 10;
        if (!n) break;
    }
 
    if (s.find(next) != s.end()) {
        cyclestart = next;
        if (cyclestart == num) ans = cnt - 1;
        return;
    }
 
    func(next, cnt + 1);
    if (num == cyclestart)
        ans = cnt - 1;
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    cin >> N >> M;
    func(N, 1);
    cout << ans << '\n';
    
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Set<Integer> s = new HashSet<>();
    static int N, M, cyclestart, ans;
 
    static void func(int num, int cnt) {
        s.add(num);
 
        int next = 0;
        int n = num;
        while (true) {
            next += Math.pow(n % 10, M);
            n /= 10;
            if (n == 0)
                break;
        }
 
        if (s.contains(next)) {
            if (next == num)
                ans = cnt - 1;
            cyclestart = next;
            return;
        }
 
        func(next, cnt + 1);
        if (cyclestart == num)
            ans = cnt - 1;
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(N, 1);
        System.out.println(ans);
    }
}
cs

'algorithm > Implementation' 카테고리의 다른 글

boj 10163 색종이  (0) 2021.02.24
boj 20055 컨베이어 벨트 위의 로봇  (0) 2021.02.23
boj 10157 자리배정  (0) 2021.02.17
boj 16918 봄버맨  (0) 2021.02.17
boj 16935 배열 돌리기 3  (0) 2021.02.10

www.acmicpc.net/problem/1826

 

1826번: 연료 채우기

첫째 줄에 주유소의 개수 N(1 ≤ N ≤ 10,000)가 주어지고 두 번째 줄부터 N+1번째 줄 까지 주유소의 정보가 주어진다. 주유소의 정보는 두개의 정수 a,b로 이루어 져 있는데 a(1 ≤ a ≤ 1,000,000)는 성경

www.acmicpc.net

1km를 가는데 연료가 1L씩 소모됩니다.

목적지까지 가는 길에 주유소가 있어서 부족한 연료를 채우고 가야합니다.

마을에 도착했을 때, 주유소를 방문한 최소 횟수를 출력하는 문제입니다. 만약 목적지에 도착하지 못하면 -1을 출력합니다.

 

저는 거리 1당 1L이므로 연료소모를 하지않고 계속 쌓으면서 목적지까지 갈 수 있는지 확인하였고, 방법은 그리디로 하였습니다.

우선 입력으로 주어지는 주유소의 정보를 거리기준으로 오름차순 정렬합니다.

그 다음 현재 연료로 갈 수 있는 지점까지 큐에 넣어주면서 이동하다가

연료보다 더 멀리있는 주유소가 나오면 지금까지 큐에 넣어두었던 연료 중 가장 높은 값을 저장합니다.

물론 이를 위해 우선순위 큐를 사용합니다.

 

이 연산을 반복하여 마지막 목적지를 기준으로 연료가 충분한지도 확인해야합니다.

충분하면 그대로 ans를 출력, 모든 주유소를 다 들려도 목적지에 가지 못하면 -1을 출력합니다.

 

 

[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
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 <algorithm>
#include <queue>
using namespace std;
 
priority_queue<int> q;
pair<intint> list[10001];
int N, des, now, ans;
 
void func() {
    int idx = 0;
    while (idx < N) {
        if (now >= list[idx].first) {
            q.push(list[idx].second);
        }
        else {
            if (q.empty()) break;
            now += q.top();
            q.pop();
            ans++;
            idx--;
        }
        idx++;
    }
    while (!q.empty()) {
        if (now >= des) break;
        
        now += q.top();
        q.pop();
        ans++;
    }
 
    if (now >= des) cout << ans << '\n';
    else cout << "-1\n";
}
 
void input() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> list[i].first >> list[i].second;
    }
    cin >> des >> now;
    sort(list, list + N);
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int list[][];
    static int N, des, now, ans;
 
    static void func() {
        PriorityQueue<Integer> q = new PriorityQueue<>();
        int idx = 0;
        while (idx < N) {
            if (now >= list[idx][0])
                q.add(-list[idx][1]);
            else {
                if (q.isEmpty())
                    break;
 
                now -= q.poll();
                ans++;
                idx--;
            }
            idx++;
        }
 
        while (!q.isEmpty()) {
            if (now >= des)
                break;
            now -= q.poll();
            ans++;
        }
 
        if (now >= des)
            System.out.println(ans);
        else
            System.out.println(-1);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N][2];
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i][0= Integer.parseInt(st.nextToken());
            list[i][1= Integer.parseInt(st.nextToken());
        }
        st = new StringTokenizer(br.readLine());
        des = Integer.parseInt(st.nextToken());
        now = Integer.parseInt(st.nextToken());
 
        Arrays.sort(list, new Comparator<int[]>() {
            @Override
            public int compare(int[] a, int[] b) {
                return a[0- b[0];
            }
        });
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > Greedy' 카테고리의 다른 글

boj 2262 토너먼트 만들기  (0) 2021.10.16
boj 13904 과제  (0) 2021.09.30
boj 8980 택배  (0) 2021.02.16
boj 11000 강의실 배정  (0) 2021.02.16
boj 1931 회의실 배정  (0) 2021.02.16

www.acmicpc.net/problem/15653

 

15653번: 구슬 탈출 4

첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'

www.acmicpc.net

보드를 4방향으로 기울여 구슬을 구멍으로 빼내는데 걸리는 최소 횟수를 출력하는 문제입니다. 구멍을 통해 빼낼 수 없으면 -1을 출력합니다.

 

시뮬레이션으로 구슬을 이동시켜야하며, 4방향으로 기울이는 것은 bfs를 이용하였습니다.

우선 큐에 입력으로 받은 빨간 구슬의 좌표, 파란 구슬의 좌표, 그리고 0(움직인 횟수)를 넣습니다.

그 다음 bfs로 구슬을 움직여줍니다.

 

구슬을 움직일 때는

1. 빨간 구슬과 파란 구슬을 벽이나 구멍이 있을때까지 움직여줍니다.

2. 만약 파란 구슬이 도중에 탈출했다면 continue (파란 구슬은 탈출하면 안됩니다.)

3. 파란 구슬이 탈출 안했고, 빨간 구슬이 탈출 했으면 cnt + 1 출력

4. 둘 다 탈출 못했으면 큐에 넣기 전에 구슬들이 겹칠 가능성이 존재하므로 확인해줍니다.

5. 구슬들이 겹쳐있으면 원래의 자리와 거리를 구해 먼 쪽이 한칸 뒤로 이동합니다.

6. 이제 다음 칸인 (nrx, nry), (nbx, nby)의 방문했는지 확인해줍니다.

7. 모두 통과되면 방문 체크를 해주고, 큐에 넣어줍니다.

8. 만약 큐가 비어있게 되면 탈출을 못했다는 뜻이므로 -1을 출력해줍니다.

 

백준에 있는 구슬 탈출 문제가 여러개 있는데 똑같은 문제인것 같네요

 

 

[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
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
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
 
typedef struct point {
    int rx;
    int ry;
    int bx;
    int by;
    int cnt;
}point;
 
queue<point> q;
bool visit[11][11][11][11];
char list[11][11];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, M;
 
void bfs() {
    while (!q.empty()) {
        int rx = q.front().rx;
        int ry = q.front().ry;
        int bx = q.front().bx;
        int by = q.front().by;
        int cnt = q.front().cnt;
        q.pop();
        
        for (int i = 0; i < 4; i++) {
            int nrx = rx;
            int nry = ry;
 
            bool redchk = false;
            bool bluechk = false;
            while (1) {
                nrx += direct[i][0];
                nry += direct[i][1];
 
                if (list[nrx][nry] == '#') {
                    nrx -= direct[i][0];
                    nry -= direct[i][1];
                    break;
                }
                else if (list[nrx][nry] == 'O') {
                    redchk = true;
                    break;
                }
            }
 
            int nbx = bx;
            int nby = by;
 
            while (1) {
                nbx += direct[i][0];
                nby += direct[i][1];
 
                if (list[nbx][nby] == '#') {
                    nbx -= direct[i][0];
                    nby -= direct[i][1];
                    break;
                }
                else if (list[nbx][nby] == 'O') {
                    bluechk = true;
                    break;
                }
            }
 
            if (bluechk) continue;
            else if (redchk) {
                cout << cnt + 1 << '\n';
                return;
            }
 
            if (nrx == nbx && nry == nby) {
                int reddis = abs(nrx - rx) + abs(nry - ry);
                int bluedis = abs(nbx - bx) + abs(nby - by);
 
                if (reddis > bluedis) {
                    nrx -= direct[i][0];
                    nry -= direct[i][1];
                }
                else {
                    nbx -= direct[i][0];
                    nby -= direct[i][1];
                }
            }
 
            if (visit[nrx][nry][nbx][nby]) continue;
 
            q.push({ nrx,nry,nbx,nby,cnt + 1 });
            visit[nrx][nry][nbx][nby] = true;
        }
    }
 
    cout << "-1\n";
}
 
void input() {
    int rx, ry, bx, by;
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
            if (list[i][j] == 'B') {
                bx = i;
                by = j;
            }
            else if (list[i][j] == 'R') {
                rx = i;
                ry = j;
            }
        }
    }
 
    q.push({ rx,ry,bx,by,0 });
    visit[rx][ry][bx][by] = true;
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    bfs();
 
    return 0;
}
cs

 

 

[Java]

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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static class Pair {
        int rx;
        int ry;
        int bx;
        int by;
        int cnt;
 
        public Pair(int rx, int ry, int bx, int by, int cnt) {
            this.rx = rx;
            this.ry = ry;
            this.bx = bx;
            this.by = by;
            this.cnt = cnt;
        }
    }
 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Deque<Pair> dq = new ArrayDeque<>();
    static boolean visit[][][][] = new boolean[11][11][11][11];
    static char list[][] = new char[11][11];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M;
 
    static void bfs() {
        while (!dq.isEmpty()) {
            int rx = dq.peek().rx;
            int ry = dq.peek().ry;
            int bx = dq.peek().bx;
            int by = dq.peek().by;
            int cnt = dq.poll().cnt;
 
            for (int i = 0; i < 4; i++) {
                int nrx = rx;
                int nry = ry;
                boolean redchk = false;
                while (true) {
                    nrx += direct[i][0];
                    nry += direct[i][1];
 
                    if (list[nrx][nry] == '#') {
                        nrx -= direct[i][0];
                        nry -= direct[i][1];
                        break;
                    }
                    if (list[nrx][nry] == 'O') {
                        redchk = true;
                        break;
                    }
                }
 
                int nbx = bx;
                int nby = by;
                boolean bluechk = false;
                while (true) {
                    nbx += direct[i][0];
                    nby += direct[i][1];
 
                    if (list[nbx][nby] == '#') {
                        nbx -= direct[i][0];
                        nby -= direct[i][1];
                        break;
                    }
                    if (list[nbx][nby] == 'O') {
                        bluechk = true;
                        break;
                    }
                }
 
                if (bluechk)
                    continue;
                else if (redchk) {
                    System.out.println(cnt + 1);
                    return;
                }
 
                if (nrx == nbx && nry == nby) {
                    int reddis = Math.abs(nrx - rx) + Math.abs(nry - ry);
                    int bluedis = Math.abs(nbx - bx) + Math.abs(nby - by);
 
                    if (bluedis < reddis) {
                        nrx -= direct[i][0];
                        nry -= direct[i][1];
                    } else {
                        nbx -= direct[i][0];
                        nby -= direct[i][1];
                    }
                }
 
                if (visit[nrx][nry][nbx][nby])
                    continue;
 
                dq.add(new Pair(nrx, nry, nbx, nby, cnt + 1));
                visit[nrx][nry][nbx][nby] = true;
            }
        }
 
        System.out.println(-1);
    }
 
    static void input() throws Exception {
        int rx = 0, ry = 0, bx = 0, by = 0;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = st.nextToken().toCharArray();
            for (int j = 0; j < M; j++) {
                if (list[i][j] == 'R') {
                    rx = i;
                    ry = j;
                } else if (list[i][j] == 'B') {
                    bx = i;
                    by = j;
                }
            }
        }
 
        dq.add(new Pair(rx, ry, bx, by, 0));
        visit[rx][ry][bx][by] = true;
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 2589 보물섬  (0) 2021.03.16
boj 11559 Puyo Puyo  (0) 2021.02.26
boj 1525 퍼즐  (0) 2021.02.19
boj 7576 토마토  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17

www.acmicpc.net/problem/17299

 

17299번: 오등큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

emoney96.tistory.com/49

 

boj 17298 오큰수

www.acmicpc.net/problem/17298 17298번: 오큰수 첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다. www.acmicpc.net 스..

emoney96.tistory.com

위의 문제와 같은 문제입니다.

오큰수는 오른쪽에 있는 자신보다 큰 수 중에 가장 왼쪽에 있는 수를 출력하는 문제이고, 

이 문제는 오른쪽에 있는 자신보다 등장횟수가 많은 수 중에 가장 왼쪽에 있는 수를 출력하는 문제입니다.

자신보다 큰 수 -> 자신보다 등장횟수가 많은 수 의 차이이며 풀이는 같습니다.

 

이 문제 역시 수열을 역순으로 탐색하였고,

list[i]를 스택에 넣기 전에 자신보다 등장횟수가 적은 값들을 모두 pop해줍니다.

 

스택이 비어있으면 -1, 아니면 top을 출력해주시면 됩니다.

 

 

[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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <stack>
using namespace std;
 
stack<int> s;
int list[1000001], num[1000001], ans[1000001];
int N;
 
void print() {
    for (int i = 1; i <= N; i++) {
        cout << ans[i] << ' ';
    }
 
    cout << '\n';
}
 
void func() {
    for (int i = N; i > 0; i--) {
        while (!s.empty() && num[list[i]] >= num[s.top()]) s.pop();
 
        if (s.empty()) ans[i] = -1;
        else ans[i] = s.top();
 
        s.push(list[i]);
    }
}
 
void input() {
    cin >> N;
    for (int i = 1; i <= N; i++) {
        cin >> list[i];
        num[list[i]]++;
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
    print();
 
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Stack<Integer> s = new Stack<>();
    static int list[], num[], ans[];
    static int N;
 
    static void print() {
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i <= N; i++)
            sb.append(ans[i]).append(" ");
        System.out.println(sb.toString());
    }
 
    static void func() {
        for (int i = N; i > 0; i--) {
            while (!s.isEmpty() && num[list[i]] >= num[s.peek()])
                s.pop();
 
            if (s.isEmpty())
                ans[i] = -1;
            else
                ans[i] = s.peek();
 
            s.push(list[i]);
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new int[N + 1];
        num = new int[1000001];
        ans = new int[1000001];
 
        st = new StringTokenizer(br.readLine());
        for (int i = 1; i <= N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
            num[list[i]]++;
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
        print();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 15926 현욱은 괄호왕이야!!  (1) 2023.07.24
boj 21939 문제 추천 시스템 Version 1  (0) 2022.02.11
boj 9372 상근이의 여행  (0) 2021.02.09
boj 1158 요세푸스 문제  (0) 2021.02.09
boj 1918 후위 표기식  (0) 2021.02.05

www.acmicpc.net/problem/14438

 

14438번: 수열과 쿼리 17

길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i v : Ai를 v로 바꾼다. (1 ≤ i ≤ N, 1 ≤ v ≤ 109) 2 i j : Ai, Ai+1, ..., Aj에서 크기가 가장 작은 값을

www.acmicpc.net

1 i v -> i번째 수를 v로 바꿉니다.

2 i j -> i ~ j 번째 수들 중에서 가장 작은 값을 출력합니다.

 

배열의 원소를 입력받을 때마다 세그먼트 트리로 최솟값을 갱신시켜줍니다.

 

그리고 쿼리를 입력받습니다.

1이면 i번째 수를 v로 바꾸는 update,

2이면 i ~ j번째 수들 중 가장 작은 값을 출력하는 query를 실행시킵니다.

현재 구간[s, e]이 찾으려는 구간[l, r]의 밖에 있으면 INF를 리턴,

완전히 포함되어있으면 tree[node]를 리턴합니다.

 

 

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
#include <iostream>
#include <algorithm>
#define INF 2147483647
using namespace std;
 
int tree[400004];
int N, M;
 
int update(int node, int s, int e, int idx, int diff) {
    if (idx < s || idx > e) return tree[node];
    if (s == e) return tree[node] = diff;
 
    int m = (s + e) / 2;
    return tree[node] = min(update(node * 2, s, m, idx, diff), update(node * 2 + 1, m + 1, e, idx, diff));
}
 
int query(int node, int s, int e, int l, int r) {
    if (l <= s && e <= r) return tree[node];
    if (l > e || r < s) return INF;
 
    int m = (s + e) / 2;
    return min(query(node * 2, s, m, l, r), query(node * 2 + 1, m + 1, e, l, r));
}
 
void func() {
    int type, a, b;
    cin >> M;
    while (M--) {
        cin >> type >> a >> b;
        if (type == 1) {
            update(11, N, a, b);
        }
        else {
            cout << query(11, N, a, b) << '\n';
        }
    }
}
 
void input() {
    int x;
    cin >> N;
    for (int i = 1; i <= N; i++) {
        cin >> x;
        update(11, N, i, x);
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

'algorithm > SegmentTree' 카테고리의 다른 글

boj 14719 빗물  (0) 2021.03.15
boj 2304 창고 다각형  (0) 2021.02.25
boj 13537 수열과 쿼리 1  (0) 2021.02.21
boj 6549 히스토그램에서 가장 큰 직사각형  (0) 2021.02.19
boj 2104 부분배열 고르기  (0) 2021.02.19

www.acmicpc.net/problem/13537

 

13537번: 수열과 쿼리 1

길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. i j k: Ai, Ai+1, ..., Aj로 이루어진 부분 수열 중에서 k보다 큰 원소의 개수를 출력한다.

www.acmicpc.net

i j k -> 배열의 i ~ j 번째 중에서 k보다 큰 수의 갯수를 출력하는 문제입니다.

저는 N개의 배열을 세그먼트트리에 저장해주고 각 구간에 포함되는 인덱스의 수를 벡터에 넣었습니다.

그리고 트리의 모든 범위를 한번씩 정렬해줍니다. (k보다 큰 수의 갯수를 찾기 위함입니다)

 

i j k 입력이 들어오면 query함수에서 찾아줍니다.

현재 들어와있는 구간[s, e]이 찾는 구간[l, r] 밖에 있으면 0을 리턴시켜주고,

완전히 포함되어있으면 tree[node]의 end - upper_bound를 리턴시켜줍니다.

 

end는 마지막원소 +1의 위치를 반환해주고,

upper_bound는 k 값을 초과하는 첫번째 숫자의 위치를 반환해줍니다.

따라서 k보다 큰 원소의 갯수를 구하려면 end - upper_bound를 해주시면 됩니다.

 

 

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
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<int> tree[400004];
int N, M;
 
void update(int node, int s, int e, int idx, int diff) {
    if (s > idx || e < idx) return;
    tree[node].push_back(diff);
    if (s == e) return;
 
    int m = (s + e) / 2;
    update(node * 2, s, m, idx, diff);
    update(node * 2 + 1, m + 1, e, idx, diff);
}
 
int query(int node, int s, int e, int l, int r, int x) {
    if (s > r || e < l) return 0;
    if (l <= s && e <= r) return tree[node].end() - upper_bound(tree[node].begin(), tree[node].end(), x);
 
    int m = (s + e) / 2;
    return query(node * 2, s, m, l, r, x) + query(node * 2 + 1, m + 1, e, l, r, x);
}
 
void func() {
    int i, j, k;
    cin >> M;
    while (M--) {
        cin >> i >> j >> k;
        cout << query(11, N, i, j, k) << '\n';
    }
}
 
void input() {
    int x;
    cin >> N;
    for (int i = 1; i <= N; i++) {
        cin >> x;
        update(11, N, i, x);
    }
 
    for (int i = 1; i <= N * 4; i++) sort(tree[i].begin(), tree[i].end());
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

'algorithm > SegmentTree' 카테고리의 다른 글

boj 2304 창고 다각형  (0) 2021.02.25
boj 14438 수열과 쿼리 17  (0) 2021.02.21
boj 6549 히스토그램에서 가장 큰 직사각형  (0) 2021.02.19
boj 2104 부분배열 고르기  (0) 2021.02.19
boj 2243 사탕상자  (0) 2021.02.04

www.acmicpc.net/problem/11049

 

11049번: 행렬 곱셈 순서

첫째 줄에 입력으로 주어진 행렬을 곱하는데 필요한 곱셈 연산의 최솟값을 출력한다. 정답은 231-1 보다 작거나 같은 자연수이다. 또한, 최악의 순서로 연산해도 연산 횟수가 231-1보다 작거나 같

www.acmicpc.net

N * M 행렬과 M * K 행렬을 곱할때는 N * M * K번의 연산이 필요합니다.

이 공식을 이용해서 여러개의 행렬을 곱하는데 필요한 곱셈 연산의 수를 최소로 해야합니다.

입력으로는 순서대로 곱셈이 가능하게 주어지므로 순서대로 연산을 할 수 있습니다.

 

저는 3중for문을 사용하였습니다.

i는 간격, x는 시작 인덱스, y는 중간 인덱스, k는 끝 인덱스를 나타내었습니다.

dp[x][k]는 dp[x][y] + dp[y + 1][k]

즉, (x ~ y번째 행렬을 곱할 때 연산의 최솟값) + (y + 1 ~ k번째 행렬을 곱할 때 연산의 최솟값) 에다가

x ~ y번째가 합쳐있는 행렬과 y + 1 ~ k번째가 합쳐있는 행렬을 곱할 때 필요한 연산을 더해주어야합니다.

 

그러면 점화식은 dp[x][k] = min(dp[x][k], dp[x][y] + dp[y + 1][k] + list[x].first * list[y].second * list[k].secod) 가 될 수 있습니다.

출력은 dp[1][N] (1 ~ N번째 행렬을 곱할 때 연산의 최솟값)로 해주시면 됩니다.

 

 

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
#include <iostream>
#include <algorithm>
using namespace std;
 
pair<intint> list[501];
int dp[501][501];
int N;
 
void func() {
    for (int i = 1; i < N; i++) {
        for (int x = 1; x + i <= N; x++) {
            int k = x + i;
            for (int y = x; y < k; y++) {
                if (!dp[x][y])
                    dp[x][k] = dp[x][y] + dp[y + 1][k] + list[x].first * list[y].second * list[k].second;
                else
                    dp[x][k] = min(dp[x][k], dp[x][y] + dp[y + 1][k] + list[x].first * list[y].second * list[k].second);
            }
        }
    }
 
    cout << dp[1][N] << '\n';
}
 
void input() {
    cin >> N;
    for (int i = 1; i <= N; i++) {
        cin >> list[i].first >> list[i].second;
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
    
    input();
    func();
 
    return 0;
}
cs

'algorithm > dp' 카테고리의 다른 글

boj 17404 RGB거리 2  (0) 2021.02.28
boj 2616 소형기관차  (0) 2021.02.27
boj 1915 가장 큰 정사각형  (0) 2021.02.20
boj 1912 연속합  (0) 2021.02.18
boj 10211 Maximum Subarray  (0) 2021.02.18

www.acmicpc.net/problem/1915

 

1915번: 가장 큰 정사각형

첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다.

www.acmicpc.net

이런식으로 배열이 주어지면 1로만 이루어진 가장 큰 정사각형의 넓이를 구하는 문제입니다.

 

우선 2 * 2의 정사각형의 예로 들면

여기서 맨 오른쪽 아래(2, 2)를 기준으로 왼쪽(2, 1), 위(1, 2), 왼쪽 위(1, 1)의 수가 모두 1이기때문에 정사각형이 됩니다.

여기서 dp[i][j]의 값은 dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]의 값들로 인해 결정이 되는것을 알 수 있습니다.

 

 

위의 그림은 dp[i - 1][j - 1]이 0이므로 정사각형이 아닙니다.

 

여기서 도출되는 점화식은 dp[i][j] += min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])입니다.

이 점화식은 현재 좌표의 값이 1일 경우에만 적용됩니다. (0일 경우에는 그냥 넘겨줍니다)

계산 과정에서 ans를 계속 갱신시켜줘서 마지막에 넓이를 출력해주시면 됩니다.

 

 

[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
25
26
27
#include <iostream>
#include <algorithm>
using namespace std;
 
int dp[1001][1001];
int N, M, ans;
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    char ch;
    cin >> N >> M;
 
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            cin >> ch;
            dp[i][j] = ch - '0';
            if (dp[i][j]) dp[i][j] += min(dp[i - 1][j], min(dp[i][j - 1], dp[i - 1][j - 1]));
            ans = max(ans, dp[i][j]);
        }
    }
 
    cout << ans * ans << '\n';
 
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int dp[][] = new int[1001][1001];
    static int N, M, ans;
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
 
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            char ch[] = st.nextToken().toCharArray();
            for (int j = 1; j <= M; j++) {
                dp[i][j] = ch[j - 1- '0';
 
                if (dp[i][j] == 1) {
                    dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j])) + 1;
                    ans = Math.max(ans, dp[i][j]);
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        System.out.println(ans * ans);
    }
}
cs

'algorithm > dp' 카테고리의 다른 글

boj 2616 소형기관차  (0) 2021.02.27
boj 11049 행렬 곱셈 순서  (0) 2021.02.20
boj 1912 연속합  (0) 2021.02.18
boj 10211 Maximum Subarray  (0) 2021.02.18
boj 10826 피보나치 수 4  (0) 2021.02.08

 

www.acmicpc.net/problem/1525

 

1525번: 퍼즐

세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

www.acmicpc.net

3 * 3 퍼즐을 이동시켜서 위와같은 상태로 만들고, 이동의 최소 횟수를 출력하고, 불가능한 경우 -1를 출력합니다.

 

저는 3 * 3 퍼즐을 String으로 변환시켰습니다.

1 0 3
4 2 5
7 8 6

입력이 이렇게 주어지면 "103425786"을 만든 다음 bfs를 돌렸습니다. (방문체크도 Set<String>으로 하였습니다.)

그리고 각 칸에서 움직일 수 있는 공간을 ArrayList배열을 만들어서 모두 만들어줍니다.

왼쪽 위 칸 번호가 0번부터 시작해서 오른쪽 아래 칸 번호가 8번이되어 

0 -> 1, 3

1 -> 0, 2, 4

2 -> 1, 5

3 -> 0, 4, 6

4 -> 1, 3, 5, 7

5 -> 2, 4, 8

6 -> 3, 7

7 -> 4, 6, 8

8 -> 5, 7

이렇게 그래프를 연결시킬 수 있습니다.

 

이제 bfs를 돌려줍니다.

덱에 입력받은 문자열(str), 0의 위치(idx), 움직인 횟수(cnt)를 넣어줍니다.

bfs 과정에서는 현재 문자열에서 idx위치와 next위치의 문자열을 서로 바꿔줍니다.

그리고 중복체크를 하고, 덱에 넣어주는 방식으로 하였습니다.

 

덱에서 꺼낸 문자열이 ans인 "123456780"과 같으면 cnt를 출력하고 리턴합니다.

만약 ans와 같은 문자열이 나오지 않았는데 덱이 비어있게되면 "123456780"을 만들수 없으므로 -1을 출력합니다.

 

 

[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
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
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <set>
using namespace std;
 
typedef struct list {
    string now;
    int idx;
    int cnt;
}list;
 
queue<list> q;
set<string> s;
vector<int> v[9];
string ans = "123456780", str = "";
 
void init() {
    v[0].push_back(1);
    v[0].push_back(3);
 
    v[1].push_back(0);
    v[1].push_back(2);
    v[1].push_back(4);
 
    v[2].push_back(1);
    v[2].push_back(5);
 
    v[3].push_back(0);
    v[3].push_back(4);
    v[3].push_back(6);
 
    v[4].push_back(1);
    v[4].push_back(3);
    v[4].push_back(5);
    v[4].push_back(7);
 
    v[5].push_back(2);
    v[5].push_back(4);
    v[5].push_back(8);
 
    v[6].push_back(3);
    v[6].push_back(7);
 
    v[7].push_back(4);
    v[7].push_back(6);
    v[7].push_back(8);
 
    v[8].push_back(5);
    v[8].push_back(7);
}
 
void bfs() {
    while (!q.empty()) {
        string now = q.front().now;
        int idx = q.front().idx;
        int cnt = q.front().cnt;
        q.pop();
 
        if (!now.compare(ans)) {
            cout << cnt << '\n';
            return;
        }
 
        for (int i = 0; i < v[idx].size(); i++) {
            int next = v[idx][i];
            string tmp = now;
            swap(tmp[idx], tmp[next]);
 
            if (s.find(tmp) != s.end()) continue;
 
            q.push({ tmp, next, cnt + 1 });
            s.insert(tmp);
        }
    }
 
    cout << "-1\n";
}
 
void input() {
    int k = 0;
    string tmp = "";
    for (int i = 0; i < 9; i++) {
        cin >> tmp;
        str += tmp;
 
        if (tmp[0== '0') {
            k = i;
        }
    }
 
    q.push({ str, k, 0 });
    s.insert(str);
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    init();
    input();
    bfs();
 
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
 
public class Main {
    static class Pair {
        String now;
        int idx;
        int cnt;
 
        public Pair(String now, int idx, int cnt) {
            this.now = now;
            this.idx = idx;
            this.cnt = cnt;
        }
    }
 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static String ans = "123456780";
    static ArrayList<Integer> list[] = new ArrayList[9];
    static String str = "";
 
    static void init() {
        for (int i = 0; i < 9; i++)
            list[i] = new ArrayList<>();
 
        list[0].add(1);
        list[0].add(3);
 
        list[1].add(0);
        list[1].add(2);
        list[1].add(4);
 
        list[2].add(1);
        list[2].add(5);
 
        list[3].add(0);
        list[3].add(4);
        list[3].add(6);
 
        list[4].add(1);
        list[4].add(3);
        list[4].add(5);
        list[4].add(7);
 
        list[5].add(2);
        list[5].add(4);
        list[5].add(8);
 
        list[6].add(3);
        list[6].add(7);
 
        list[7].add(4);
        list[7].add(6);
        list[7].add(8);
 
        list[8].add(5);
        list[8].add(7);
    }
 
    static void bfs() {
        Set<String> s = new HashSet<>();
        Deque<Pair> dq = new ArrayDeque<>();
        dq.add(new Pair(str, str.indexOf("0"), 0));
        s.add(new String(str));
        while (!dq.isEmpty()) {
            String now = dq.peek().now;
            int idx = dq.peek().idx;
            int cnt = dq.poll().cnt;
 
            if (now.equals(ans)) {
                System.out.println(cnt);
                return;
            }
 
            for (int i = 0; i < list[idx].size(); i++) {
                int next = list[idx].get(i);
                char newstr[] = new String(now).toCharArray();
                char tmp = newstr[idx];
                newstr[idx] = newstr[next];
                newstr[next] = tmp;
 
                String s1 = String.valueOf(newstr);
                if (s.contains(s1))
                    continue;
 
                dq.add(new Pair(s1, next, cnt + 1));
                s.add(new String(s1));
            }
        }
 
        System.out.println(-1);
    }
 
    static void input() throws Exception {
        for (int i = 0; i < 3; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < 3; j++) {
                str += st.nextToken();
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        init();
        input();
        bfs();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 11559 Puyo Puyo  (0) 2021.02.26
boj 15653 구슬 탈출 4  (0) 2021.02.22
boj 7576 토마토  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17
boj 16236 아기 상어  (0) 2021.02.14

www.acmicpc.net/problem/7576

 

7576번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토

www.acmicpc.net

bfs를 이용하여 익은 토마토와 근접해있는 토마토를 익게해서 모든 토마토를 익혀야합니다.

하지만 토마토가 들어있지 않은 칸이 있기때문에 모든 토마토가 익지 않을 수도 있습니다.

그리고 입력으로 이미 모든 토마토가 익어있으면 0을 출력해야합니다.

 

우선 입력을 받고, 0의 갯수(ans)를 모두 세어 유지합니다.

그리고 1을 입력받으면 덱에 넣고 방문처리도 해줍니다. (bfs 사용)

그 다음 bfs를 돌리기 전에 이미 ans가 0이면 0을 출력하고 리턴합니다.

 

확인이 끝나면 bfs를 돌려줍니다.

하루에 한칸씩 번지기때문에 덱에 있던 좌표들만 돌려야합니다. (t로 날짜 계산)

for문을 덱이 비어있지 않을동안 돌려주고 현재 덱의 크기를 size에 넣어서 size 만큼만 bfs를 돌려줍니다. (1일치)

 

이후에 ans가 0이 되면 모두 익었다는 뜻이므로 t를 출력합니다.

ans가 0이 되지 않았는데 덱이 비어버리면 모두 익지 않았다는 뜻이므로 -1을 출력합니다.

 

 

[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
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
#include <iostream>
#include <queue>
using namespace std;
 
queue<pair<intint> > q;
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
bool visit[1001][1001];
int list[1001][1001];
int N, M, ans;
 
void bfs() {
    int t = 1;
    for (; !q.empty(); t++) {
        int qsize = q.size();
        while (qsize--) {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
 
            for (int i = 0; i < 4; i++) {
                int nx = x + direct[i][0];
                int ny = y + direct[i][1];
                
                if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
                if (visit[nx][ny] || list[nx][ny] == -1continue;
 
                q.push({ nx,ny });
                visit[nx][ny] = true;
                ans--;
            }
        }
 
        if (!ans) {
            cout << t << '\n';
            return;
        }
    }
 
    cout << "-1\n";
}
 
void func() {
    if (!ans) {
        cout << "0\n";
        return;
    }
 
    bfs();
}
 
void input() {
    cin >> M >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
            if (!list[i][j])
                ans++;
            else if (list[i][j] == 1) {
                q.push({ i,j });
                visit[i][j] = true;
            }
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Deque<int[]> dq = new ArrayDeque<>();
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static boolean visit[][];
    static int list[][];
    static int N, M, ans;
 
    static void bfs() {
        int t = 1;
        for (; !dq.isEmpty(); t++) {
            int size = dq.size();
 
            while (size-- > 0) {
                int x = dq.peekFirst()[0];
                int y = dq.pollFirst()[1];
 
                for (int i = 0; i < 4; i++) {
                    int nx = x + direct[i][0];
                    int ny = y + direct[i][1];
 
                    if (nx < 0 || ny < 0 || nx >= N || ny >= M)
                        continue;
                    if (list[nx][ny] == -1 || visit[nx][ny])
                        continue;
 
                    visit[nx][ny] = true;
                    dq.addLast(new int[] { nx, ny });
                    ans--;
                }
            }
 
            if (ans == 0)
                break;
        }
        if (ans == 0)
            System.out.println(t);
        else
            System.out.println(-1);
    }
 
    static void func() {
        if (ans == 0) {
            System.out.println(0);
            return;
        }
 
        bfs();
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        visit = new boolean[N][M];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
                if (list[i][j] == 0)
                    ans++;
                else if (list[i][j] == 1) {
                    dq.addLast(new int[] { i, j });
                    visit[i][j] = true;
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 15653 구슬 탈출 4  (0) 2021.02.22
boj 1525 퍼즐  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17
boj 16236 아기 상어  (0) 2021.02.14
boj 10026 적록색약  (0) 2021.02.13

www.acmicpc.net/problem/6549

 

6549번: 히스토그램에서 가장 큰 직사각형

입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤

www.acmicpc.net

emoney96.tistory.com/138

 

boj 2104 부분배열 고르기

www.acmicpc.net/problem/2104 2104번: 부분배열 고르기 크기가 N(1≤N≤100,000)인 1차원 배열 A[1], …, A[N]이 있다. 어떤 i, j(1≤i≤j≤N)에 대한 점수는, (A[i]+…+A[j])×Min{A[i], …, A[j]}가 된다. 즉,..

emoney96.tistory.com

이 문제와 같은 풀이방법입니다.

세그먼트 트리로 구간의 최솟값만 트리에 저장하였습니다.

 

구간 [l, r]의 최솟값의 인덱스를 query함수로 찾아내고 list[idx]에 구간의 길이를 곱한 값이 직사각형의 넓이입니다.

idx를 기준으로 왼쪽(l, idx - 1) 구간, 오른쪽(idx + 1, r) 구간의 넓이와 [l, r]에서 구했던 넓이의 최댓값을 출력하면 됩니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static int tree[] = new int[400004];
    static long list[] = new long[100001];
    static int N;
 
    static int init(int node, int s, int e) {
        if (s == e)
            return tree[node] = s;
 
        int m = (s + e) / 2;
        int l = init(node * 2, s, m);
        int r = init(node * 2 + 1, m + 1, e);
        return tree[node] = list[l] < list[r] ? l : r;
    }
 
    static int query(int node, int s, int e, int l, int r) {
        if (l > e || s > r)
            return -1;
        if (l <= s && e <= r)
            return tree[node];
 
        int m = (s + e) / 2;
        int a = query(node * 2, s, m, l, r);
        int b = query(node * 2 + 1, m + 1, e, l, r);
 
        if (a == -1)
            return b;
        else if (b == -1)
            return a;
        else
            return list[a] < list[b] ? a : b;
    }
 
    static long func(int l, int r) {
        int idx = query(11, N, l, r);
        long sum = list[idx] * (r - l + 1);
 
        if (idx > l)
            sum = Math.max(sum, func(l, idx - 1));
        if (idx < r)
            sum = Math.max(sum, func(idx + 1, r));
 
        return sum;
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        if (N == 0)
            return;
 
        for (int i = 1; i <= N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
        }
        init(11, N);
    }
 
    public static void main(String[] args) throws Exception {
        while (true) {
            input();
            if (N == 0)
                break;
            sb.append(func(1, N)).append("\n");
        }
        
        System.out.println(sb.toString());
    }
}
cs

'algorithm > SegmentTree' 카테고리의 다른 글

boj 14438 수열과 쿼리 17  (0) 2021.02.21
boj 13537 수열과 쿼리 1  (0) 2021.02.21
boj 2104 부분배열 고르기  (0) 2021.02.19
boj 2243 사탕상자  (0) 2021.02.04
boj 2042 구간 합 구하기  (0) 2021.01.23

www.acmicpc.net/problem/2104

 

2104번: 부분배열 고르기

크기가 N(1≤N≤100,000)인 1차원 배열 A[1], …, A[N]이 있다. 어떤 i, j(1≤i≤j≤N)에 대한 점수는, (A[i]+…+A[j])×Min{A[i], …, A[j]}가 된다. 즉, i부터 j까지의 합에다가 i부터 j까지의 최솟값을 곱한 것이

www.acmicpc.net

www.acmicpc.net/problem/6549

 

6549번: 히스토그램에서 가장 큰 직사각형

입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤

www.acmicpc.net

이문제와 같은 방법으로 해결하였습니다.

 

우선 세그먼트 트리로 구간 합과 최솟값을 모두 tree배열에 저장하였습니다.

그 다음 func함수에서 [s, e]구간의 최솟값의 인덱스(idx)과 구간 합(query)을 찾아내어 곱한 값을 sum에 저장하고,

idx를 기준으로 왼쪽(s, idx - 1), 오른쪽(idx + 1, e) 구간으로 나누어 각각의 sum의 최댓값을 찾은 후에 출력하였습니다.

이 방법말고 다른방법으로 해결하는 방법이 있던데 알려주신 분의 코드를 뜯어봐야 할 것 같습니다...

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static long tree[][] = new long[400004][2];
    static int list[] = new int[100001];
    static int N;
 
    static long[] init(int node, int s, int e) {
        if (s == e) {
            tree[node][0= list[s];
            tree[node][1= s;
            return tree[node];
        }
 
        int m = (s + e) / 2;
        long l[] = init(node * 2, s, m);
        long r[] = init(node * 2 + 1, m + 1, e);
        tree[node][0= l[0+ r[0];
        if (list[(int) l[1]] < list[(int) r[1]])
            tree[node][1= l[1];
        else
            tree[node][1= r[1];
        return tree[node];
    }
 
    static long query(int node, int s, int e, int l, int r) {
        if (s > r || l > e)
            return 0;
        if (l <= s && e <= r)
            return tree[node][0];
 
        int m = (s + e) / 2;
        return query(node * 2, s, m, l, r) + query(node * 2 + 1, m + 1, e, l, r);
    }
 
    static long findmin(int node, int s, int e, int l, int r) {
        if (s > r || l > e)
            return -1;
        if (l <= s && e <= r)
            return tree[node][1];
 
        int m = (s + e) / 2;
        long a = findmin(node * 2, s, m, l, r);
        long b = findmin(node * 2 + 1, m + 1, e, l, r);
        if (a == -1)
            return b;
        else if (b == -1)
            return a;
        else {
            if (list[(int) a] > list[(int) b])
                return b;
            else
                return a;
        }
    }
 
    static long func(int s, int e) {
        int idx = (int) findmin(11, N, s, e);
        long sum = query(11, N, s, e) * list[idx];
 
        if (s < idx)
            sum = Math.max(sum, func(s, idx - 1));
        if (idx < e)
            sum = Math.max(sum, func(idx + 1, e));
 
        return sum;
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        st = new StringTokenizer(br.readLine());
        for (int i = 1; i <= N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
        }
 
        init(11, N);
    }
 
    public static void main(String[] args) throws Exception {
        input();
        System.out.println(func(1, N));
    }
}
cs

'algorithm > SegmentTree' 카테고리의 다른 글

boj 14438 수열과 쿼리 17  (0) 2021.02.21
boj 13537 수열과 쿼리 1  (0) 2021.02.21
boj 6549 히스토그램에서 가장 큰 직사각형  (0) 2021.02.19
boj 2243 사탕상자  (0) 2021.02.04
boj 2042 구간 합 구하기  (0) 2021.01.23

+ Recent posts