반응형

문제출처

https://www.acmicpc.net/problem/2098


문제풀이

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
/**
 * n이 16까지 주어지는데 모든 경우의 수는 16!로 굉장히 큰 것을 예상할 수 있습니다.
 * => 처음 1번도시를 방문하고 다음도시를 방문할 수 있는 경우의 수는 n-1이며 그 다음은 n-2이기 때문에 n!의 시간복잡도를 가집니다.
 * 처음에 dfs와 같은 방법으로 전체탐색을 수행하려 했지만 시간제한이 1초여서 다른 방법을 생각하던 중
 * DP를 사용하면 해결될듯 하여 해당 주제인 비트마스크와 DP를 사용했습니다.
 *
 * 비트마스크 visit로 사용
 * 만약 4개의 도시중 방문한 도시가 없다면 0000으로 표현할 수 있습니다. 1번 도시를 방문한 경우 0001
 * 2번도시를 방문한 경우는 0010 이와 같이 1번 3번도시를 방문했다면 0101으로 표현할 수 있습니다.
 * 때문에 모든 도시를 방문한 경우 1111로 나타낼수 있습니다.
 * 여기서 중요한 것은 하나하나의 비트가 0이면 방문하지 않은 상태를 뜻하고 1이면 방문한 것을 의미합니다.
 *
 * 그럼 방문여부를 체크할때는 어떻게 할까 고민해 봐야한다. 예제에서 볼 수 있듯이 1->3의 값과 3->1의 가중치가 다릅니다.
 * 즉, 현재 출발도시도 중요한 영향을 미치며 방문여부도 값에 영향을 미치는 것을 알 수 있습니다.
 * 이를 통해 dp배열의 구조를 생각할 수 있습니다. dp[현재도시][방문한도시]와 같이 표현할 수 있습니다.
 * 예를 들면 1,2,3번 도시를 방문했고 현재 3번도시에 위치한 경우 최소거리를 dp[3][0111](dp[3][7])로 나타낼 수 있습니다.
 * 여기서 레퍼런스 변수 &ret을 사용했는데 dp배열을 사용해도 문제없습니다. 레퍼런스 변수는 dp배열의 인덱스값을 확실하게 참조할 수 있는
 * 장점이 있습니다. 레퍼런스 변수 자체가 참조하는 주소를 기억하기 때문에 더 안정적이라고 하네요.
 * 이 문제는 0번도시, 4번도시 아무도시에서 시작해도 항상 같은 값을 가집니다. 왜냐하면 사이클이기 때문이죠.
 * 만약 경로가 있다는 가정하에 1->2->3->4->1 의값은 2->3->4->1->2 의 값과 같습니다. 2의 왼쪽은 1 // 2의오른쪽은 3 이런식으로 비교하면
 * 사이클이므로 값이 같다는 것을 알 수 있습니다. 때문에 저는 0번도시에서 시작을 하는 것으로 풀이를 시작했습니다.
* (다시 한번 강조하지만 어떤 도시든지 상관이 없습니다.)
 *
 * INF값을 0x7fffffff값을 주었는데 이경우 시간초과가 떴습니다. 왜 시간초과인지는 모르겠지만 1만 더해도 int범위를 벗어나기 때문에
 * 문제가 있을것이라 생각하고 10억이 넘는값으로 수정하니 맞았습니다.
 */
cs


소스코드

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
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAX 16
 
using namespace std;
 
int n;
int map[MAX][MAX];
int dp[MAX][1<<MAX];
 
int tsp(int cur, int visit) {
    //방문한 곳은 재방문하지 않았으므로 다시 원점으로 돌아오는 가중치를 return해줘서 더해준다.
   if(visit == (1<<n)-1)
       return (map[cur][0]>0) ? map[cur][0] : INF;
   int &ret=dp[cur][visit];
   if(ret>0)   return ret;
   ret=INF;
   for(int i=0; i<n; i++) {
       if(!(visit & (1<<i)) && map[cur][i]>0) {
           ret=min(ret, tsp(i, visit|(1<<i)) + map[cur][i]);
       }
   }
   return ret;
}
 
int main() {
    ios_base::sync_with_stdio(false); cout.tie(0); cin.tie(0);
    cin>>n;
    for(int i=0; i<n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> map[i][j];
        }
    }
    cout<<tsp(0,1)<<endl;
    return 0;
}
 
cs


반응형

'Algorithm' 카테고리의 다른 글

[BOJ 7562] 나이트의 이동  (0) 2019.01.28
[BOJ 9663] N-Queen  (0) 2019.01.28
[CodeForce] 158A - Next Round  (0) 2019.01.25
[CodeForce] 71A - Way Too Long Words  (0) 2019.01.25
[BOJ 10163] 색종이  (0) 2019.01.24

+ Recent posts