공부/백준

14889번: 스타트와 링크(백준 C++)

상연 2020. 11. 12. 16:05

목차

    14889번: 스타트와 링크 링크

    코드

    #include <iostream>
    #include <vector>
    #include <climits>
    using namespace std;
    
    int arr[21][21];
    bool check[21] = {0, };
    
    vector <int> v(1, 1);
    
    int min_num = INT_MAX;
    
    int n;
    
    void init(){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                cin >> arr[i][j];
            }
        }
    }
    
    void solve(int cnt, int x){
        if(cnt == (n/2 - 1)){
            vector <int> v2;
            int temp1 = 0;
            int temp2 = 0;
            int k = 2;
            for(int i=2; i<=n; i++){
                v2.push_back(i);
                for(int j=0; j<v.size(); j++){
                    if(i == v[j]){
                        v2.pop_back();
                        continue;
                    }
                }
            }
            for(int j=0; j<v.size(); j++){
                for(int k=(j+1); k<v.size(); k++){
                    temp1 += arr[v[j]][v[k]];
                    temp1 += arr[v[k]][v[j]];
                    temp2 += arr[v2[j]][v2[k]];
                    temp2 += arr[v2[k]][v2[j]];
                }
            }
            min_num = abs(temp1 - temp2) < min_num ? (abs(temp1 - temp2)) : min_num; 
        }
        else{
            for(int i=x; i<=n; i++){
                if(check[i] == 1) continue;
                check[i] = 1;
                v.push_back(i);
                solve(cnt+1, i+1);
                v.pop_back();
                check[i] = 0;
            }
        }    
    }
    
    int main() {
        cin >> n;
        init();
        solve(0, 2);
        cout << min_num;
        // your code goes here
        return 0;
    }

    풀이 및 사견

    음... 뭔가 되게 복잡하게 풀었다는 느낌을 버릴수가없다.
    그렇지만 일단 정답은 정답이니까..?

    우선 이 문제 풀이에는 N과 M(2) 풀이 방법을 채용했다.

    이게 무슨 뜻이냐면

    위 그림의 경우에는 N이 4이다. 팀을 2:2로 나누어야 한다는 뜻이다.

    그런데 잘 생각해보면 4개 중 2개를 고르면 나머지 2개는 자동으로 선택이된다.

    딱히 팀을 나누는 것에 대한 구분은 없기때문에...

    Team1 : Team2
    [1, 2] : [3, 4] - CASE1

    Team1 : Team2
    [3, 4] : [1, 2] - CASE2

    위 CASE1과 CASE2는 동일하다.

    그렇기 때문에 N이 4라고 가정시, 찾아봐야 할 경우의 수는 3가지가 된다.

    4C2 / 2 = 6 / 2 = 3

    4명중 2명을 고르는 경우의 수.

    1) 1 2 / 3 4
    2) 1 3 / 2 4
    3) 1 4 / 2 3
    4) 2 3 / 1 4
    5) 2 4 / 1 3
    6) 3 4 / 1 2

    여기서 1-6 / 2-5 / 3-4 는 동일하므로 다시 경우의 수를 반으로 나누면 3가지이다.

    즉, 우리는 (1, 2) (1, 3), (1, 4) 만 찾으면 되는데

    규칙이 있다. N이 계속 커져도 찾아야 하는 경우의 수에는 항상 1이 들어간다.

    N이 6일때를 보자.

    6C3 / 2 = 10 , 10가지인데

    1) 1 2 3
    2) 1 2 4
    3) 1 2 5
    4) 1 2 6
    5) 1 3 4
    6) 1 3 5
    7) 1 3 6
    8) 1 4 5
    9) 1 4 6
    10) 1 5 6

    그렇다면 이를 통해 우리는 선택할 수 있다.
    탐색소요시간을 줄이기 위해서 2 ~ N 까지의 수 중 N/2 - 1 개의 수를 선택하는 경우의 수를 찾고 그 경우의 수에 1을 추가해주면 된다.

    이를 백트래킹으로 구현하면.

    for(int i=x; i<=n; i++){
                if(check[i] == 1) continue;
                check[i] = 1;
                v.push_back(i);
                solve(cnt+1, i+1);
                v.pop_back();
                check[i] = 0;
       }

    이렇게 나온다.

    이 문제를 풀기 귀찮았던게 좀 이것저것 더할것도 많고 해서 그런건데

    벡터 v에는 경우의 수중 하나의 경우가 들어있다. (예 - N이 4일때 v = [1, 2])
    그럼 반대로 벡터v2에는 1~N중 벡터 v에 없는 수를 찾아서 넣어 경우를 생성한다.(v2 = [3, 4])

    이후 문제 조건에 따라 능력치를 더해준 후 빼 본뒤 최소값을 구해주면 문제가 풀린다.

    '공부 > 백준' 카테고리의 다른 글

    1003번: 피보나치 함수(백준 C++)  (0) 2020.11.14
    2748번: 피보나치 수2(백준 C++)  (0) 2020.11.13
    14888번: 연산자 끼워넣기(백준 C++)  (0) 2020.11.11
    2580번: 스도쿠(백준 C++)  (0) 2020.11.10
    9663번: N-Queen(백준 C++)  (0) 2020.11.09