본문 바로가기
컴퓨터 사이언스/BOJ

[c++] 백준 #10971 외판원 순회 2

by 제크와 죠세핀 2021. 1. 24.
반응형

이번 문제는 TSP(Travelling Salesman Problem)이라 하여 굉장히 익숙한 내용을 다루는 문제이다. 

간단하게 내용을 요약해보자면, N개의 도시를 모두 다 방문하면서 처음 도시로 돌아가려고 할 때 가장 최소의 비용을 출력하는 문제이다.

 

www.acmicpc.net/problem/10971

 

10971번: 외판원 순회 2

첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 10) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j

www.acmicpc.net

<풀이>

나는 dfs + 비트마스킹으로 문제를 풀었다.

맨처음 시작지점을 1~N까지 모두 돌아가면서 dfs를 돌리면 된다. 너무 전형적인 dfs 풀이가 가능하다.

섬에 방문할 때마다 다음 섬을 이미 방문하지 않았으면서 && 간선이 존재하는 그런 곳으로 방문하면 된다.

마지막에 ending condition으로는 모든 섬을 다 돌았고, 처음 지점으로 간선이 존재하면 value를 리턴하게 하면 된다.

 

크게 어려울 것 없는 구현이지만, 내가 실수했던 부분은 다음 투어를 진행할 때 val을 미리 더해주고(주석처리한 부분) 함수를 호출해서 다음 도시를 확인할 때 문제가 생긴 것이다. 기본적으로 dfs 나 back tracking을 할 때에는 undo를 하는 과정을 고려해서 짜줘야하는데 그것을 실수했다. (visited를 표시하는 course 변수의 경우, 새로운 도시를 새로 visit한 이후에 call by value로 복사된 값을 변화시키기 때문에 문제가 되지 않는다.)

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
#define INF 987654321
typedef long long ll;
typedef pair<int, int> ii;
typedef tuple<int, int, int> iii;
#define pb push_back

int cost[11][11];
int ans = INF;
int N;

int tour(int starting, int current, int course, int val){
    // set that we visited this city
    course |= (1 << current);

    // if we visited all city and there exists a way to comeback, return the value
    if(__builtin_popcount(course)==N && cost[current][starting]){
        val += cost[current][starting];
        return val;
    }
    

    int ret = INF;
    for (int i=1; i<=N;i++){
        // if already visited, continue
        if (course & (1 << i)) continue;

        else if (cost[current][i] && (i != starting)){
            //val += cost[current][i];
            ret = min(ret, tour(starting, i, course, val + cost[current][i]));
        }
    }

    return ret;
}

int main(){
    cin >> N;
    for (int i=1; i<=N;i++){
        for (int j=1; j<=N; j++){
            cin >> cost[i][j];
        }
    }

    for (int i=1; i<=N;i++){
        ans = min(ans, tour(i, i, 0, 0));
    }

    cout << ans << '\n';
    return 0;
}
반응형

'컴퓨터 사이언스 > BOJ' 카테고리의 다른 글

[c++] 백준 #1201 NMK  (0) 2021.01.24
[c++] 백준 #9663 N-Queen  (0) 2021.01.24
[c++] 백준 #1339 단어 수학  (0) 2021.01.15
[c++] 백준 #16490 외계인의 침투  (0) 2019.11.05
[c++] 백준 #5000 빵정렬  (0) 2019.11.05

댓글