반응형

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

 

4991번: 로봇 청소기

각각의 테스트 케이스마다 더러운 칸을 모두 깨끗한 칸으로 바꾸는 이동 횟수의 최솟값을 한 줄에 하나씩 출력한다. 만약, 방문할 수 없는 더러운 칸이 존재하는 경우에는 -1을 출력한다.

www.acmicpc.net

 

먼저 각 좌표 사이의 거리를 모두 구해줍니다.

그 뒤, 가능한 청소 순서를 모두 만들어내서 최소의 거리를 구해줬습니다.

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
#include <vector>
#define INF 987654321
using namespace std;
int w, h, ox, oy, ans, nums[10];
char map[20][20];
bool visit[20][20], nvisit[10];
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
int d[20][20][20][20] = { 0 };
vector<pair<int, int>> pos;

bool setDist() {
    pos.push_back({ ox, oy });
    for (int i = 1; i < pos.size(); i++) {
        int cnt = 0;
        int cx = pos[i].first;
        int cy = pos[i].second;
        memset(visit, false, sizeof(visit));
        queue<pair<pair<int, int>, int>> q;
        visit[cx][cy] = true;
        q.push({ { cx, cy }, 0 });
        while (!q.empty()) {
            int x = q.front().first.first;
            int y = q.front().first.second;
            int c = q.front().second;
            if (map[x][y] == '*') {
                d[x][y][cx][cy] = d[cx][cy][x][y] = c;
                cnt++;
                if (cnt == pos.size() - 1) break;
            }
            q.pop();
            for (int j = 0; j < 4; j++) {
                int nx = x + dx[j];
                int ny = y + dy[j];
                if (nx < 0 || ny < 0 || nx >= h || ny >= w) continue;
                if (visit[nx][ny]) continue;
                if (map[nx][ny] == 'x') continue;
                visit[nx][ny] = true;
                q.push({ { nx, ny }, c + 1 });
            }
        }
        if (cnt != pos.size() - 1) return false;
    }
    pos.pop_back();
    return true;
}

void dfs(int c) {
    if (c == pos.size()) {
        int dist = 0, tx = ox, ty = oy;
        for (int i = 0; i < c; i++) {
            dist += d[tx][ty][pos[nums[i]].first][pos[nums[i]].second];
            tx = pos[nums[i]].first;
            ty = pos[nums[i]].second;
        }
        ans = min(ans, dist);
        return;
    }
    for (int i = 0; i < pos.size(); i++) {
        if (nvisit[i]) continue;
        nvisit[i] = true;
        nums[c] = i;
        dfs(c + 1);
        nvisit[i] = false;
    }
}
int main() {
    while (scanf("%d %d", &w, &h) && w) {
        ans = INF;
        pos.clear();
        for (int i = 0; i < h; i++)
            for (int j = 0; j < w && scanf(" %c", &map[i][j]); j++)
                if (map[i][j] == '*') pos.push_back({ i, j });
                else if (map[i][j] == 'o') ox = i, oy = j;
        if (setDist()) dfs(0);
        printf("%d\n", ans == INF ? -1 : ans);
    }
}
반응형

'Algorithm' 카테고리의 다른 글

백준 9376 : 탈옥  (0) 2021.11.12
백준 9328 : 열쇠  (0) 2021.11.12
백준 6087 : 레이저 통신  (0) 2021.11.12
백준 15558 : 점프 게임  (0) 2021.11.12
C언어 멱집합 구하기 : 반복문(iteration)과 재귀(recursion)  (0) 2021.11.12

+ Recent posts