Problem
Problem URL : 점심 식사시간
[1] Answer Code (18. 10. 11)
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<functional>
#include<algorithm>
#define p pair<int,int>
using namespace std;
int n;
int ans;
int map[11][11];
struct Node{
int x;
int y;
int target;
int value;
Node(int _x, int _y) : x(_x), y(_y) {};
Node(int _x, int _y, int _value) : x(_x), y(_y), value(_value){};
};
vector<Node> n_v; // n_v is node vector
vector<Node> s_v; // s_v is stair vector
int distance(int n_idx, int s_idx){
int x = abs(n_v[n_idx].x - s_v[s_idx].x);
int y = abs(n_v[n_idx].y - s_v[s_idx].y);
return x + y ;
}
void dfs(int idx){
if(idx == n_v.size()){
int people_cnt = (int) n_v.size();
int time = 0;
int exit_cnt = 0;
queue<int> waiting[2];
queue<int> stair[2];
// 각자 원하는 계단으로 가기 위한 거리 계산
for(int i=0; i<people_cnt; i++){
int dis = distance(i, n_v[i].target);
waiting[n_v[i].target].push(dis);
}
/*
작업 순서
1. time++
2. 계단에 있는 인원 내려가기
3. 계단에 인원 추가하기
*/
while (exit_cnt < people_cnt) {
time ++;
// 계단에 있는 인원 내려가기
for(int i=0; i<2; i++){
int size = (int) stair[i].size();
for(int j=0; j<size; j++){
int top = stair[i].front();
stair[i].pop();
top--;
if(top != 0)
stair[i].push(top);
else
exit_cnt++;
}
}
// 계단에 인원 추가하기
for(int i=0; i<2; i++){
int size = (int) waiting[i].size();
for(int j=0; j<size; j++){
int dis = waiting[i].front();
waiting[i].pop();
dis--;
if(dis <= 0){
if(stair[i].size() < 3){ // 계단에 도착했지만 내려가는 인원이 Full
stair[i].push(s_v[i].value);
}
else{
waiting[i].push(dis);
}
}
else{
waiting[i].push(dis);
}
}
}
} // end of while
/*
ans 구할 때
time + 1해주는 이유
000
130
000 과 같이 주어졌다고 가정하자.
내 로직대로라면
time : 1초
3번 작업 수행 --> stair에 push
time : 2초
2번 작업 수행 --> 남은 시간 2초
time : 3초
2번 작업 수행 --> 남은 시간 1초
time : 4초
2번 작업 수행 --> 남은 시간 0초
이렇게 while문을 탈출한다.
그런데 이때 답은 4초가 아닌 5초를 출력해야한다.
그래서 while문을 탈출한 시간(=time)에 +1를 해준다.
*/
ans = ans < time+1 ? ans : time+1;
} // end of if
else {
for(int i=0; i<2; i++){
n_v[idx].target = i;
dfs(idx+1);
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int TC;
cin >> TC;
for(int tc=1; tc<=TC; tc++){
memset(map,0,sizeof(map));
n_v.clear();
s_v.clear();
cin >> n;
ans = 2e9;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
int tmp;
cin >> tmp;
if(tmp == 1)
n_v.push_back(Node(i,j));
else if( tmp > 1)
s_v.push_back(Node(i,j,tmp));
}
}
dfs(0);
cout << "#" << tc << " " << ans << '\n';
}
}
Review
-
자잘한 실수로 오래걸렸다.
-
[1] : while (exit_cnt < people_cnt)가 아닌
while (exit_cnt < n)로 해서 시간초과 -
[2] : if(stair[i].size() < 3)가 아닌
if(stair[i].size() <= 3)으로 했다. 그러면 동시에 4명이 내려가게 되는 상황이 발생된다. -
그래도 만족스러운 풀이였다.
[2] Answer Code (18. 08. 30)
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define p pair<int,int>
using namespace std;
int n,ans;
int map[10][10];
int dir[10];
vector<p> pos_stairs; // position of stairs
vector<int> time_stairs;
vector<p> pos_people; // position of people
void solve(){
int time = 0;
int size = (int) pos_people.size();
int to_exit_people = size;
vector<int> people;
queue<int> stairs[2];
// 각 사람마다 목표 계단까지의 거리 구하기
for(int i=0; i<size; i++){
int _x, _y;
_x = abs(pos_people[i].first - pos_stairs[dir[i]].first);
_y = abs(pos_people[i].second - pos_stairs[dir[i]].second);
people.push_back(_x+_y+1); // 도착 후 1분이 지나야 내려갈 수 있기 때문에 +1
}
while (to_exit_people) {
time++;
for(int i=0; i<size; i++){
// [1]
if( people[i] == -1 )
continue;
// people[i] - 1 == 0 은 1초 후 계단으로 내려갈 수 있는 사람
// people[i] == 0 은 바로 내려갈 수 있는데 계단이 Full이라서 못내려가는 사람
else if(people[i] - 1 == 0 || people[i] == 0){
if( stairs[ dir[i] ].size() < 3){
stairs[ dir[i] ].push(time_stairs[ dir[i] ]);
people[i] = -1;
}
}
else{
people[i] --;
}
/*
//[2]
if(people[i] == -1 )
continue;
else if(people[i] == 0){
if( stairs[ dir[i] ].size() < 3){
stairs[ dir[i] ].push(time_stairs[ dir[i] ]);
people[i] --;
}
}
else {
people[i] --;
if( people[i] ==0 && stairs[ dir[i] ].size() < 3){
stairs[ dir[i] ].push(time_stairs[ dir[i] ]);
people[i] --;
}
}
*/
}
int queue_size = (int) stairs[0].size();
while (queue_size--) {
int top = stairs[0].front();
stairs[0].pop();
top --;
if(top == 0)
to_exit_people--;
else{
stairs[0].push(top);
}
}
queue_size = (int) stairs[1].size();
while (queue_size--) {
int top = stairs[1].front();
stairs[1].pop();
top --;
if(top == 0)
to_exit_people--;
else{
stairs[1].push(top);
}
}
} // end of While
ans = ans > time ? time : ans;
}
void dfs(int idx){
if(idx == pos_people.size()){
solve();
}
else{
for(int i=0; i<2; i++){
dir[idx] = i;
dfs(idx+1);
}
}
}
int main(){
int TC;
cin >> TC;
for (int tc=1; tc<=TC; tc++) {
cin >> n;
ans = 2e9;
memset(map,0,sizeof(map));
memset(dir,0,sizeof(dir));
pos_stairs.clear();
time_stairs.clear();
pos_people.clear();
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
scanf("%d",&map[i][j]);
if(map[i][j] == 1)
pos_people.push_back({i,j});
else if(map[i][j] > 1){
pos_stairs.push_back({i,j});
time_stairs.push_back(map[i][j]);
}
}
}
dfs(0);
printf("#%d %d\n",tc, ans+1);
} // end of for tc
return 0;
}
Review
-
머릿속으로는 구현이 되는데 그걸 코드화 시키는 작업이 어려웠다
-
포기하려했는데 해보자해서 도전해서 1번에 성공했다. 매우 뿌듯하다 !
-
[2]으로 했는데 문제를 풀면서 중복되는 코드를 줄일 수 없을까 생각한 후 문제 풀이를 끝낸 후 [1]으로 바꿨다.