알고리즘/백준

BOJ2098/ C++

내이름은 킹햄찌 2022. 1. 26. 17:21

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

 

2098번: 외판원 순회

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

www.acmicpc.net

백준 온라인저지 2098번 문제입니다. 

비트마스크, DP를 이용해서 풀었습니다.

TSP라고도 부르는데요

문제 자체가 TSP인 문제입니다.

#include<iostream>
#define INF 987654321
#define MAX 16

using namespace std;

int dp[1 << MAX][MAX];
int arr[MAX][MAX];
int n;
void Input() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
		}
	}
}

//visit 방문한 도시에 대한 비트 마스킹
//current 이번에 지날 도시
int TSP(int visit, int current) {

	//current번 도시 방문 추가 
	visit |= (1 << current);

	if (visit == (1 << n) - 1) {
		if (arr[current][0]) {
			return arr[current][0];
		}
		return INF;
	}


	//dp 개념 적용
	if (dp[visit][current] > 0)
		return dp[visit][current];
	dp[visit][current] = INF;

	for (int i = 0; i < n; i++) {

		//current -> 아직 방문하지 않은 i번 도시 가는 경로가 있는 경우
		if (i != current && (visit&(1 << i)) ==0 && arr[current][i] > 0) { 

			//최소 비용 갱신
			int temp = TSP(visit, i) + arr[current][i];
			if (dp[visit][current] > temp)
				dp[visit][current] = temp;

		}
	}
	return dp[visit][current];
}

void solution() {
	int sol = TSP(0, 0);
	cout << sol;
}

int main(void) {
	Input();
	solution();
}

아이디어

TSP 대표문제임

TSP는 브루트포스랑 아주 비슷하다는 느낌을 받는 것 같은데 완전히 이해하는데는 시간이 좀 걸렸던 것 같음

재귀를 이용하였고 1 2 3 4번 도시를 모두 방문 해야한다고 했을때 방문했을때를 1 방문하지 않았을때를 0으로 하여

4비트로 0000 1111 0101 1010과 같이 표현할 수 있음 
재귀를 이용하여 각각의 도시를 모두 방문해야할때 최소비용을 찾아야함 -> 모두 확인해봐야함

아래는 코드에서 visit의 비트는 아래와 같이 바뀌는데 손으로 풀면서 가장 이해를 도왔던 다이어그램임

 

0001 ->  0011  -> 0111 -> 1111

                     -> 1011 -> 1111

       ->  0101  -> 0111 -> 1111

                     ->1101 -> 1111

       ->  1001  -> 1011 -> 1111

                    -> 1101 -> 1111