λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ”₯ PS(Problem Solving) πŸ”₯/BOJ

[BOJ] #1021 νšŒμ „ν•˜λŠ” 큐

by dar0m! 2020. 1. 11.
μ‹œκ°„ μ œν•œ λ©”λͺ¨λ¦¬ μ œν•œ μ •λ‹΅ λΉ„μœ¨
 2 초 128 MB 43.582%

 

 

1021번: νšŒμ „ν•˜λŠ” 큐

첫째 쀄에 큐의 크기 Nκ³Ό 뽑아내렀고 ν•˜λŠ” 수의 개수 M이 주어진닀. N은 50보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄κ³ , M은 N보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€. λ‘˜μ§Έ μ€„μ—λŠ” 지민이가 뽑아내렀고 ν•˜λŠ” 수의 μœ„μΉ˜κ°€ μˆœμ„œλŒ€λ‘œ 주어진닀. μœ„μΉ˜λŠ” 1보닀 ν¬κ±°λ‚˜ κ°™κ³ , N보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.

www.acmicpc.net

 

문제

μ§€λ―Όμ΄λŠ” N개의 μ›μ†Œλ₯Ό ν¬ν•¨ν•˜κ³  μžˆλŠ” μ–‘λ°©ν–₯ μˆœν™˜ 큐λ₯Ό 가지고 μžˆλ‹€. μ§€λ―Όμ΄λŠ” 이 νμ—μ„œ λͺ‡ 개의 μ›μ†Œλ₯Ό 뽑아내렀고 ν•œλ‹€.

μ§€λ―Όμ΄λŠ” 이 νμ—μ„œ λ‹€μŒκ³Ό 같은 3가지 연산을 μˆ˜ν–‰ν•  수 μžˆλ‹€.

  1. 첫 번째 μ›μ†Œλ₯Ό 뽑아낸닀. 이 연산을 μˆ˜ν–‰ν•˜λ©΄, μ›λž˜ 큐의 μ›μ†Œκ°€ a1, ..., akμ΄μ—ˆλ˜ 것이 a2, ..., ak와 같이 λœλ‹€.
  2. μ™Όμͺ½μœΌλ‘œ ν•œ μΉΈ μ΄λ™μ‹œν‚¨λ‹€. 이 연산을 μˆ˜ν–‰ν•˜λ©΄, a1, ..., akκ°€ a2, ..., ak, a1이 λœλ‹€.
  3. 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ μ΄λ™μ‹œν‚¨λ‹€. 이 연산을 μˆ˜ν–‰ν•˜λ©΄, a1, ..., akκ°€ ak, a1, ..., ak-1이 λœλ‹€.

큐에 μ²˜μŒμ— ν¬ν•¨λ˜μ–΄ 있던 수 N이 주어진닀. 그리고 지민이가 뽑아내렀고 ν•˜λŠ” μ›μ†Œμ˜ μœ„μΉ˜κ°€ 주어진닀. (이 μœ„μΉ˜λŠ” κ°€μž₯ 처음 νμ—μ„œμ˜ μœ„μΉ˜μ΄λ‹€.) μ΄λ•Œ, κ·Έ μ›μ†Œλ₯Ό 주어진 μˆœμ„œλŒ€λ‘œ λ½‘μ•„λ‚΄λŠ”λ° λ“œλŠ” 2번, 3번 μ—°μ‚°μ˜ μ΅œμ†Ÿκ°’μ„ 좜λ ₯ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

ν•΄κ²°

λ‹¨μˆœ κ΅¬ν˜„μœΌλ‘œ headλ₯Ό 처음 μ‹œμž‘ μœ„μΉ˜λ‘œ λ³΄μ•˜κ³ , 각각 μ™Όμͺ½μœΌλ‘œ νšŒμ „ν•  λ•Œ, 였λ₯Έμͺ½μœΌλ‘œ νšŒμ „ν•  λ•Œλ₯Ό ν•¨μˆ˜ func 의 두 번째 인자 dir둜 κ΅¬λΆ„ν•˜μ—¬μ„œ 0 이면 3번 μ—°μ‚° 1 이면 2번 연산을 μ˜λ―Έν•œλ‹€. 각각 λ°©ν–₯μ—μ„œ 뽑아내렀고 ν•˜λŠ” 수의 μœ„μΉ˜κΉŒμ§€μ˜ 거리λ₯Ό λΉ„κ΅ν•˜μ—¬ 더 짧은 λ°©ν–₯을 μ„ νƒν•œλ‹€. 선택할 λ•ŒλŠ” chk 배열에 1둜 λ‚˜νƒ€λ‚΄κ³ , headλ₯Ό μ΄λ™μ‹œμΌ°λ‹€.

 

μ½”λ“œ

λ©”λͺ¨λ¦¬ μ‹œκ°„
1984 KB 0 ms
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
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
typedef pair<intint> p;
int n, m, pos[55], arr[55], chk[55], head=0, ans;
p func( int next, int dir) {
    int cnt = 0, headCopy = head;
    int d = dir ? 1 : n - 1;
    while ( arr[headCopy] != next) {
        headCopy = (headCopy + d) % n;
        if (chk[headCopy]) continue;
        cnt++;
    }
    return { cnt , headCopy };
}
int main() {
    scanf("%d %d"&n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%d"&pos[i]);
    }
    for (int i = 0; i < n; i++) arr[i] = i;
 
    for (int i = 0; i < m; i++) {
        int next = pos[i] - 1, cnt;
        if (head == next) {
            chk[head] = 1;
            cnt = 1;
            int flg = 0;
            for (int j = 0; j < n; j++)
                if (!chk[j]) flg = 1;
            if (flg) {
                while (chk[(head + cnt) % n]) cnt++;
                head = (head + cnt) % n;
            } 
            continue;
        }
 
        p left = func(next, 0);
        p right = func(next, 1);
        if (right.first < left.first) {
            ans += right.first;
            chk[right.second] = 1;
            cnt = 1;
            while (chk[(right.second + cnt) % n]) cnt++;
            head = (right.second + cnt) % n;
        }
        else {
            ans += left.first;
            chk[left.second] = 1;
            cnt = 1;
            while (chk[(left.second + cnt) % n]) cnt++;
            head = (left.second + cnt) % n;
        }
    }
    printf("%d", ans);
    return 0;
}
cs

 

멋진 방법

μ—΄μ‹¬νžˆ κ³ λ―Όν•΄μ„œ μ½”λ“œλ₯Ό μ§°λ‹€κ³  μƒκ°ν–ˆμ§€λ§Œ λ§žμ€ μ‚¬λžŒ μ½”λ“œλ₯Ό λ³΄λ‹ˆ 더 쒋은 아이디어가 μžˆμ—ˆλ‹€.

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int n, m, i, k, c, a[99];
int main() {
    scanf("%d%d"&n, &m);
    for (i = 0; i < m; i++)
        scanf("%d"&a[i]), a[i]--;
    for (i = 0; i < m; i++) { 
        c += a[i] > n-- / 2 ? n + 1 - a[i] : a[i]; 
        for (k = i + 1; k < m; k++)
            a[k] = (a[k] - a[i] + n) % (n + 1) % n; 
    }
    printf("%d\n", c);
}
cs

 

λŒ“κΈ€