https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5-BEE6AK0DFAVl



처음에 문제를 보고 1시간 동안 어떻게 풀까 고민했었다.

상하좌우 이동을 할 때마다 모든 경우를 DFS로 돌리자니 너무 복잡해 질거 같아서 고민을 하다가

계단이 오직 2가지 밖에 없고 N이 10 이하인 점을 보고 미리 계단 수를 지정할 수 있도록 접근했다.

다행히 pass를 하였지만, N제한과 계단의 수가 늘어났을 때 어떻게 풀어야할지는 더 고민을 해봐야 할 것 같다.


먼저 접근 방향은 다음과 같다.


1) 사람마다 어떤 계단으로 갈지를 DFS 함수를 통해 지정한다. (1번 계단/2번 계단)

2) 모든 사람의 계단을 지정했다면 지정한 계단과의 거리 값을 구한 뒤에 이동을 시작한다.

3) 만약 계단에 도착하고 아무도 없다면 계단에서의 이동을 시작한다.

4) 계단에 도착했지만 3명 이상이 이동을 하고 있다면, 대기해준 뒤에 다시 3번 작업을 반복한다.

5) 위의 작업을 마쳤다면, 다시 1번 작업으로 돌아가 다른 계단을 지정해줄 때 시간을 구해준다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <iostream>
#include <vector>
#include <queue>
#include <math.h>
using namespace std;
 
int N;
int ans=0;
vector<vector<int>> map;
vector<pair<int,int>> person_location;  //방 안의 사람들 위치
vector<pair<int,int>> stair_location;   //계단 위치
 
vector<int> person_stair;   //방 안의 사람들이 선택한 계단 번호 (1,2)
 
int move(){
    
    int n=(int)person_location.size(); // 사람 수
    int finish=0//완료된 사람
    int total_time=0;
    
    queue<int> q[2]; //계단에 있는 사람들 남은 시간
    
    vector<int> dist(n,0);
    for(int i=0;i<n;i++){
        int y=person_location[i].first; //현재 y좌표
        int x=person_location[i].second; //현재 x좌표
        int sy=stair_location[person_stair[i]].first; //선택한 계단 y좌표
        int sx=stair_location[person_stair[i]].second; //선택한 계단 x좌표
        
        dist[i]=abs(y-sy)+abs(x-sx);
    }
    
    while(true){
        
        if(finish==n)
            break;
        
        for(int i=0;i<n;i++){
            
            if(dist[i]<0)
                continue;
            
            if(dist[i]==0){ //계단 위치
                
                if(q[person_stair[i]].size()<3){
                    int sy=stair_location[person_stair[i]].first; //선택한 계단 y좌표
                    int sx=stair_location[person_stair[i]].second; //선택한 계단 x좌표
                    q[person_stair[i]].push(map[sy][sx]);
                    dist[i]=-1;
                }
                
                continue;
            }
            
            dist[i]-=1;
        }
        
        
        //계단에 있는 사람들 이동
        for(int i=0;i<2;i++){
            
            int cnt=(int)q[i].size();
            for(int j=0;j<cnt;j++){
                int t=q[i].front();
                q[i].pop();
                if(t>1)
                    q[i].push(t-1);
                else
                    finish++;
            }
        }
        
        total_time++;
        
    }
    
    return total_time+1;
}
void dfs(int pos){
    
    if(pos==person_location.size()){
        ans=min(ans,move());
        return;
    }
    
    person_stair[pos]=0//1번 계단
    dfs(pos+1);
    
    person_stair[pos]=1//2번 계단
    dfs(pos+1);
    
    return;
}
int main(){
    
    int T;
    cin>>T;
    for(int testCase=1;testCase<=T;testCase++){
        
        scanf("%d",&N);
        map=vector<vector<int>> (N,vector<int>(N,0));
        
        ans=99999999;
        person_location.clear();
        stair_location.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)
                    person_location.push_back(make_pair(i,j));
                else if(map[i][j]>1)
                    stair_location.push_back(make_pair(i,j));
            }
        }
        
        person_stair=vector<int> (person_location.size(),0);
        dfs(0);
        
        printf("#%d %d\n",testCase,ans);
    }
    
    return 0;
}
 
cs




'알고리즘(SWEA) > 시뮬레이션' 카테고리의 다른 글

SWEA 5644번 - 무선충전  (0) 2019.10.09
SWEA 5650번 - 핀볼게임  (0) 2019.09.01

+ Recent posts