Solution
- DFS로 각 사람이 내려갈 계단을 선택하고, 각 계단에서 모든 사람이 내려가는 시간을 구해 그 중 최소가 되는 순열을 구한다.
Point
- 각 사람이 내려갈 계단을 어떻게 선택해야하는 지를 생각하는 것이 까다로웠는데, 결론적으로 계단이 2개 뿐이기 때문에 모든 경우의 수를 고려해도 2^N이 되고 N<=10이기 때문에 최대 1024 가지의 경우의 수를 가진다. 따라서 모든 경우의 수를 DFS로 탐색해보아도 시간 안에 문제를 풀 수 있기 때문에 가지치기 없이 모든 경우를 DFS 탐색하면 된다.
- 계단 내려가는 시간 구할 때, 먼저 각 사람이 해당 계단까지 내려가는 거리를 구해 이를 기반으로 pq에 넣어 min heap을 만들고, 거리가 짧아 먼저 도착한 사람부터 한번에 3명씩 차례로 내려가게 해서 시간을 구한다.
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
typedef struct Person {
int id, x, y, time, s, dist; //s:stair id
}Person;
struct compare
{
bool operator()(const Person & a, const Person & b)
{
return a.dist > b.dist;
}
};
typedef struct Stair {
int x, y, k;
priority_queue<Person, vector<Person>, compare> q;
}Stair;
int T, N, result;
int dx[4] = { 1, -1, 0 , 0 };
int dy[4] = { 0, 0, -1, 1 };
vector<Person> people;
vector<Stair> stairs;
void input() {
result = 987654321;
people.clear();
stairs.clear();
cin >> N;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int n;
cin >> n;
if (n == 1) people.push_back({ (int)people.size(), i, j, 0, 0, 0 });
else if (n > 1) stairs.push_back({ i, j, n });
}
}
}
int countTime() {
int rt = 0;
for (int i = 0; i < people.size(); i++) {
people[i].dist = abs(people[i].x - stairs[people[i].s].x) + abs(people[i].y - stairs[people[i].s].y);
people[i].time = abs(people[i].x - stairs[people[i].s].x) + abs(people[i].y - stairs[people[i].s].y);
stairs[people[i].s].q.push(people[i]);
}
for (int i = 0; i < stairs.size(); i++) {
int count = 0;
int prev[3] = { 0 }; //three people getting down
while (!stairs[i].q.empty()) {
Person cur_p = stairs[i].q.top();
stairs[i].q.pop();
if(cur_p.time < prev[count % 3])
cur_p.time = prev[count % 3] + stairs[i].k;
else
cur_p.time += stairs[i].k + 1;
prev[count % 3] = cur_p.time;
rt = max(rt, prev[count % 3]);
count++;
}
}
return rt;
}
void dfs(int d) {
if (d == people.size()) {
result = min(countTime(), result);
return;
}
for (int i = 0; i < stairs.size(); i++) {
people[d].s = i; //choose a stair
dfs(d + 1);
}
}
int main()
{
freopen("input.txt", "r", stdin);
cin >> T;
for (int t = 1; t <= T; t++) {
input();
dfs(0);
cout << "#" << t << " " << result << endl;
}
}
'알고리즘 ·코딩 공부 > SWEA 문제 풀이' 카테고리의 다른 글
[시뮬레이션] SWEA2382 미생물 격리 (0) | 2019.03.13 |
---|---|
[DFS] SWEA2115 벌꿀채취 (0) | 2019.02.22 |
[BFS] SWEA1953 탈주범 검거 (0) | 2019.02.20 |
[DFS] SWEA2105 디저트 카페 (0) | 2019.02.20 |
[DFS] SWEA2112 보호 필름 (0) | 2019.02.19 |