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

[BOJ] #14889 μŠ€νƒ€νŠΈμ™€ 링크

by dar0m! 2019. 10. 2.
μ‹œκ°„ μ œν•œ λ©”λͺ¨λ¦¬ μ œν•œ μ •λ‹΅ λΉ„μœ¨
2 초 512 MB 50.576%

 

 

14889번: μŠ€νƒ€νŠΈμ™€ 링크

예제 2의 κ²½μš°μ— (1, 3, 6), (2, 4, 5)둜 νŒ€μ„ λ‚˜λˆ„λ©΄ 되고, 예제 3의 κ²½μš°μ—λŠ” (1, 2, 4, 5), (3, 6, 7, 8)둜 νŒ€μ„ λ‚˜λˆ„λ©΄ λœλ‹€.

www.acmicpc.net

 

방법 1 : vector 이용

Brute Force 둜 μŠ€νƒ€νŠΈνŒ€μ˜ ꡬ성원을 ꡬ해고, μŠ€νƒ€νŠΈνŒ€μ˜ ꡬ성원을 기반으둜 λ§ν¬νŒ€μ˜ ꡬ성원을 μ•Œμ•„λ‚Έλ‹€. κ·Έλ ‡κ²Œ νŒ€μ˜ ꡬ성원을 μ•Œμ•„λ‚Έ 후에 각 νŒ€μ˜ λŠ₯λ ₯치λ₯Ό κ³„μ‚°ν•˜μ—¬ λΉ„κ΅ν•˜κ³  MIN 값을 맀번 κ°±μ‹ μ‹œν‚¨λ‹€.

  • ν•¨μˆ˜ μ„€λͺ…
    인자 idxλŠ” 인덱슀 μˆœμ„œλ₯Ό λ‚˜νƒ€λ‚΄κ³ , cnt λŠ” μŠ€νƒ€νŠΈνŒ€μ˜ ꡬ성원이 μ•„λ‹Œ μ‚¬λžŒμ˜ μˆ«μžμ΄λ‹€. μŠ€νƒ€νŠΈνŒ€κ³Ό λ§ν¬νŒ€μ˜ ꡬ성원은 무쑰건 n/2 λͺ…μ΄λ―€λ‘œ μŠ€νƒ€νŠΈνŒ€μ˜ ꡬ성원이 μ•„λ‹Œ μ‚¬λžŒμ˜ μˆ«μžλŠ” n/2λ₯Ό λ„˜μ–΄κ°ˆ 수 μ—†λ‹€. λ”°λΌμ„œ cnt κ°€ n/2λ₯Ό λ„˜μ–΄κ°€λ©΄ return ν•˜λ„λ‘ ν•˜μ˜€λ‹€.

 

λ©”λͺ¨λ¦¬ μ‹œκ°„
1176 KB 20 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
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
int n, arr[25][25], chk[25], MIN = 10000;
vector<int> team1, team2;
void go(int idx, int cnt) {
    if (idx > n || cnt > n/2return;
    if (team1.size() == n / 2) {
        // μ–‘μͺ½μ˜ νŒ€ λŠ₯λ ₯치λ₯Ό λΉ„κ΅ν•˜μ—¬ MIN κ°’을 κ΅¬ν• κ±°μž„.
        int sumteam1 = 0, sumteam2 = 0;
        for (int i = 0; i < team1.size(); i++) {
            chk[team1[i]] = 1;
            for (int j = i+1; j < team1.size(); j++) {
                sumteam1 += arr[team1[i]][team1[j]] + arr[team1[j]][team1[i]];
            }
        }
        for (int i = 1; i <= n; i++) {
            if (!chk[i]) team2.push_back(i);
        }
        for (int i = 0; i < team2.size(); i++) {
            for (int j = i + 1; j < team2.size(); j++) {
                sumteam2 += arr[team2[i]][team2[j]] + arr[team2[j]][team2[i]];
            }
        }
        MIN = min(MIN, abs(sumteam1 - sumteam2));
        team2.clear(); memset(chk, 0sizeof(chk));
        return;
    }
    team1.push_back(idx);
    go(idx + 1, cnt);
    team1.pop_back();
    go(idx + 1, cnt + 1);
}
int main() {
    scanf("%d"&n);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            scanf("%d"&arr[i][j]);
        }
    }
    go(10);
    printf("%d", MIN);
    return 0;
}
cs

맀번 κΈ°μ €λ‹¨κ³„μ—μ„œ λ°°μ—΄ μ΄ˆκΈ°ν™”λ₯Ό μ‹œμΌœμ•Όν•˜κΈ° λ•Œλ¬Έμ— 뢀담이 큰 단점이 μžˆλ‹€. κ·Έλž˜μ„œ 방법 2λ₯Ό μ‚¬μš©ν•΄ λ³΄μ•˜λ‹€.

 

방법 2 : vector 이용 μ‹œκ°„ 단좕.

이 방법은 맀번 n 크기의 배열을 λͺ¨λ‘ νƒμƒ‰ν•΄μ•Όν•˜μ§€λ§Œ 배열을 μ΄ˆκΈ°ν™”ν•΄μ•Όν•˜λŠ” 뢀담이 적어지기 λ•Œλ¬Έμ— μ‹œκ°„μ΄ 크게 μ ˆμ•½λ˜μ–΄ '방법 1'보닀 효율적인 μ½”λ“œκ°€ λœλ‹€.

그리고 '방법 1'μ—μ„œ μ‚¬μš©ν–ˆλ˜ cntλ₯Ό 방법 2μ—μ„œ μ‚¬μš©ν•˜λ©΄ n λͺ…μ˜ νŒ€μ› λͺ¨λ‘λ₯Ό λ§Œλ‚  수 μ—†μ–΄ μ˜ˆμƒν•˜λŠ” κ²°κ³Όκ°’κ³Ό λ‹€λ₯Έ 값이 λ‚˜μ˜€κ²Œ λ˜μ–΄ λΉΌμ£Όμ–΄μ•Ό ν•œλ‹€. 

λ©”λͺ¨λ¦¬ μ‹œκ°„
1176 KB 4 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
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
int n, arr[25][25], MIN = 10000;
vector<int> team1, team2;
void go(int idx) {
    if (!MIN) return// μ°¨μ΄κ°€ 0이라면 λ” μ΄μƒ λ³΄μ§€ μ•Šμ•„도 λ¨. 
    if (idx > n) {
        // μ–‘μͺ½μ˜ νŒ€ λŠ₯λ ₯치λ₯Ό λΉ„κ΅ν•˜μ—¬ MIN κ°’을 κ΅¬ν•œλ‹€.
        int sumteam1 = 0, sumteam2 = 0;
        for (int i = 0; i < team1.size() - 1; i++) {
            for (int j = i + 1; j < team1.size(); j++) {
                sumteam1 += arr[team1[i]][team1[j]] + arr[team1[j]][team1[i]];
                sumteam2 += arr[team2[i]][team2[j]] + arr[team2[j]][team2[i]];
            }
        }
        MIN = min(MIN, abs(sumteam1 - sumteam2));
        return;
    }
    if (team1.size() < n / 2) {
        team1.push_back(idx);
        go(idx + 1);
        team1.pop_back();
    }
    if (team2.size() < n / 2) {
        team2.push_back(idx);
        go(idx + 1);
        team2.pop_back();
    }
}
int main() {
    scanf("%d"&n);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            scanf("%d"&arr[i][j]);
        }
    }
    go(1);
    printf("%d", MIN);
    return 0;
}
cs

 

방법 3 : int λ°°μ—΄ 이용

λ©”λͺ¨λ¦¬λ„, μ‹œκ°„λ„ λͺ¨λ‘ μ ˆμ•½λ˜λŠ” 졜적의 방법이닀.

λ©”λͺ¨λ¦¬ μ‹œκ°„
1116 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
#include<cstdio>
#include<math.h>
int n, a[20][20], t1[10], t2[10], an, bn, ans = 1e5;
void go(int x) {
    if (!ans) return;
    if (x == n) {
        int s1 = 0, s2 = 0;
        for (int i = 0; i < n / 2 - 1; i++)
            for (int j = i + 1; j < n / 2; j++) {
                s1 += a[t1[i]][t1[j]] + a[t1[j]][t1[i]];
                s2 += a[t2[i]][t2[j]] + a[t2[j]][t2[i]];
            }
        s1 = abs(s1 - s2);
        ans = ans < s1 ? ans : s1;
        return;
    }
    if (an < n / 2) {
        t1[an++= x;
        go(x + 1);
        an--;
    }
    if (bn < n / 2) {
        t2[bn++= x;
        go(x + 1);
        bn--;
    }
}
int main() {
    scanf("%d"&n);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            scanf("%d"&a[i][j]);
    go(0);
    printf("%d", ans);
}
cs

 

 

마무리

μŠ€νƒ€νŠΈμ™€ 링크λ₯Ό ν’€λ©΄μ„œ vectorκ°€ 일반 int 배열보닀 λ©”λͺ¨λ¦¬μ™€ μ‹œκ°„μ„ 많이 μ‚¬μš©ν•˜κ²Œ λœλ‹€λŠ” 점을 크게 κΉ¨λ‹«κ²Œ λ˜μ—ˆλ‹€. λ¬Όλ‘  λ©”λͺ¨λ¦¬λΆ€λΆ„은 헀더?의 영ν–₯이 μžˆμ„ 것 κ°™μ§€λ§Œ! ν™•μ‹€νžˆ 인덱슀둜만 μ›€μ§μ΄λŠ” 것과 ν•¨μˆ˜(pop_back, push_back)을 μ“°λŠ” 것은 큰 μ°¨μ΄κ΅¬λ‚˜ μ‹Άμ—ˆλ‹€.

'πŸ”₯ PS(Problem Solving) πŸ”₯ > BOJ' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[BOJ] #1010 닀리놓기  (0) 2019.10.02
[BOJ] #14891 ν†±λ‹ˆλ°”ν€΄  (0) 2019.10.02
[BOJ] #3190 λ±€  (0) 2019.09.29
[BOJ] #16929 Two Dots  (0) 2019.09.29
[BOJ] #6359 λ§Œμ·¨ν•œ 상범  (0) 2019.09.19

λŒ“κΈ€