https://www.acmicpc.net/problem/5852
5852번: Island Travels
Farmer John has taken the cows to a vacation out on the ocean! The cows are living on N (1 <= N <= 15) islands, which are located on an R x C grid (1 <= R, C <= 50). An island is a maximal connected group of squares on the grid that are marked as 'X', wher
www.acmicpc.net
대강 해설
소들은 N(1 <= N <= 15)개의 섬 위에 있습니다. 섬은 R x C (1 <= R, C <= 50)의 크기 입니다. 섬의 위치는 X로 표시되어 있으며 좌우로 연결되어 있는 X는 동일한 섬입니다. 처음에 방문할 수 있는 섬은 아무곳이나 상관없으며 각 섬을 최소 한번씩 방문하면 됩니다. S는 수영을 하여 지나갈 수 있습니다. 최소한의 수영 횟수로 모든 섬을 방문하는 횟수를 구해주세요.
. : 깊은 물 (수영 불가 - 못 지나감)
X : 섬의 위치
S : 얇은 물 (수영 가능)
과정
- 연결되어 있는 X를 하나의 섬으로 묶는다.
- 각각의 섬들 사이의 거리를 구한다.(모든 섬울 방문하는 최소 거리를 구해야 되기 때문에)
- 모든 섬을 시작점으로 한번씩 외판원 순회 알고리즘(Traveling Salesman Problem)을 이용하여 최소 거리를 구한다.
예제
더보기
5 4
XX.S
.S..
SXSS
S.SX
..SX
정답 : 3
3 5
XSXSX
..S..
..X..
정답 : 4
코드
더보기
#include<iostream>
#include<vector>
#include<queue>
#include<climits>
using namespace std;
typedef struct Data{
int y,x,cost;
}d;
struct compare{
bool operator()(d &a, d &b){
return a.cost > b.cost;
}
};
int my[4]={0,1,0,-1};
int mx[4]={1,0,-1,0};
int R,C;
char map[55][55];
int chk[1 << 17][20];
int visit_map[55][55];
int dist[20][20];
int cnt=1;
void input(){
cin>>R>>C;
for(int i=0;i<R;i++){
for(int j=0;j<C;j++){
cin>>map[i][j];
}
}
}
void make_island(int y, int x, int num){
map[y][x]=num;
for(int m=0;m<4;m++){
int ny=y+my[m];
int nx=x+mx[m];
if(ny<0||nx<0||ny>=R||nx>=C||map[ny][nx]!='X')
continue;
make_island(ny,nx,num);
}
}
void connect_island(){
fill(&dist[1][0],&dist[19][20],INT_MAX);
for(int i=0;i<R;i++){
for(int j=0;j<C;j++){
if(map[i][j]=='X'){
make_island(i,j,cnt);
cnt++;
}
}
}
}
void make_map(int sy, int sx, int cow){
fill(&visit_map[0][0],&visit_map[54][55],INT_MAX);
priority_queue<d, vector<d>, compare> q;
visit_map[sy][sx]=0;
dist[cow][cow]=0;
q.push({sy,sx,0});
while(!q.empty()){
int y = q.top().y;
int x = q.top().x;
int cost = q.top().cost;
q.pop();
if(visit_map[y][x] < cost)
continue;
if(map[y][x] < cnt)
dist[cow][map[y][x]] = min(cost, dist[cow][map[y][x]]);
for(int m=0;m<4;m++){
int ny = y+my[m];
int nx = x+mx[m];
if(ny<0||nx<0||ny>=R||nx>=C||map[ny][nx]=='.')
continue;
int ncost = cost + (map[ny][nx] == 'S');
if(visit_map[ny][nx] > ncost){
visit_map[ny][nx] = ncost;
q.push({ny,nx,ncost});
}
}
}
}
int tsp(int vst, int now){
if(chk[vst][now] != 0 ) return chk[vst][now];
if(vst == (1 << cnt) -1) return chk[vst][now] = 0;
int ret = INT_MAX;
for(int i=1;i<cnt;i++){
if(vst & (1 << i)) continue;
ret = min(ret, tsp((vst | (1 << i)), i) + dist[now][i]);
}
return chk[vst][now] = ret;
}
void solution(){
for(int i=0;i<R;i++){
for(int j=0;j<C;j++){
if(map[i][j]<cnt && dist[map[i][j]][map[i][j]]!=0){
make_map(i,j,map[i][j]);
}
}
}
cout<<tsp(1,0)<<'\n';
}
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
input();
connect_island();
solution();
return 0;
}

728x90
'알고리즘 > 백준 문제' 카테고리의 다른 글
| [ALGORITHM] 백준 5901 - Relocation (0) | 2022.10.01 |
|---|---|
| [Algorithm] 백준 9874 - Wormholes (0) | 2022.09.30 |
| [ALGORITHM] 백준 5827 - What's Up With Gravity (0) | 2022.09.28 |
| [ALGORITHM] 백준 17825 - 주사위 윷놀이 (0) | 2022.06.07 |
| [Algorithm] 백준 17822 - 원판 돌리기 (0) | 2022.05.31 |
댓글