ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 20130 (Metroidvania Extreme)
    전공/알고리즘 2020. 11. 11. 14:21

    www.acmicpc.net/problem/20130

     

    20130번: Metroidvania Extreme

    첫 번째 줄에는 지금까지 기록한 좌표의 수 k을 출력한다. 이후 k개의 줄에 걸쳐 기록한 순서대로 방문한 칸의 행 번호와 열 번호를 공백으로 구분하여 출력한다.

    www.acmicpc.net

    이 문제를 풀면서 감탄을 정말 많이 했다. 

     

    일단 bfs문제인데, bfs의 성질을 잘 알아야 순간이동이 무슨소리인지 이해가 될거라고 생각한다. 

     

    개인적으로 무슨 소리인지 모르겠으면 혼자 깨달을때까지 생각해보는거 추천

     

    이 문제의 핵심은 bfs로 풀 수 있다는 걸 아는 것이라고 생각한다. 

    그리고 a가 없이 A를 만났을때 어떻게 해야할지 아는것? 생각하면 된다. 

    그냥 어떻게 자료를 저장하고 후에 처리를 할지 생각해보자 

     

    자료를 어떻게 저장 처리할지는 어떤 방식으로 작동하는지 생각하면 알 수 있다.

     

    뭐 나머지는 그냥 구현에서의 주의점? 

     

    이 문제에서는 주의할 점이 여러개가 있다. 

     

    제일 헤맨부분은 a,A가 최대 하나라고 생각하고 풀었었다. 최소와 최대갯수는 정해지지 않아있다. 

    그리고 visit을 언제할지, queue에 언제 넣을지 주의해야하는 것 같다. 

     

    진짜 좋은 문제라고 생각한다. 

     

    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    #define MAX 205
    
    queue<pair<int, int> > q;
    queue<pair<int, int> > ans;
    queue<pair<int, int> > v[MAX];
    pair<int, int> start;
    pair<int, int> fin;
    int N, M;
    int dx[4] = { 1,-1,0,0 };
    int dy[4] = { 0,0,1,-1 };
    char mat[MAX][MAX];
    bool visit[MAX][MAX];
    bool haveal[MAX];
    
    void bfs() {
    	q.push(start);
    	visit[start.first][start.second] = true;
    	ans.push(start);
    	while (!q.empty()) {
    		int x = q.front().first;
    		int y = q.front().second;
    		q.pop();
    		for (int i = 0; i < 4; i++) {
    			int nx = x + dx[i];
    			int ny = y + dy[i];
    			if (nx == fin.first && ny == fin.second) {
    				ans.push(fin);
    				return;
    			}
    			if (visit[nx][ny] || mat[nx][ny] == '#')continue;
    			int a = (int)mat[nx][ny];
    			if (a >= 65 && a <= 90 && !haveal[a + 32]){
    				v[a + 32].push({ nx,ny });
    				continue;
    			}
    			visit[nx][ny] = true;
    			q.push({ nx,ny });
    			ans.push({ nx,ny });
    			if (a >= 97 && a <= 122) {
    				haveal[a] = true;
    				while(!v[a].empty()){
    					int k = v[a].front().first;
    					int l = v[a].front().second;
    					v[a].pop();
    					if (!visit[k][l]) {
    						visit[k][l] = true;
    						ans.push({ k,l });
    						q.push({ k,l });
    					}
    				}
    			}
    		}
    	}
    }
    
    int main() {
    	ios_base::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	cin >> N >> M;
    	for (int i = 1; i <= N; i++) {
    		for (int j = 1; j <= M; j++) {
    			char a;
    			cin >> a;
    			mat[i][j] = a;
    			if (a == '@') {
    				start.first = i;
    				start.second = j;
    			}
    			if (a == '!') {
    				fin.first = i;
    				fin.second = j;
    			}
    		}
    	}
    	bfs();
    	cout << ans.size() << "\n";
    	while (!ans.empty()) {
    		cout << ans.front().first << " " << ans.front().second << "\n";
    		ans.pop();
    	}
    }

     

     

    '전공 > 알고리즘' 카테고리의 다른 글

    백준 5582(공통 부분 문자열)  (0) 2020.11.16
    백준 20130 (Metroidvania Extreme)  (0) 2020.11.11
    백준 20128(Parity Constraint Shortest Path)  (0) 2020.11.10
    백준 20127(Y-수열)  (0) 2020.11.10
    백준 13751(Barbells)  (0) 2020.10.26

    댓글

Designed by Tistory.