Hello Ocean! 🌼

[C++/ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€] 블둝 μ΄λ™ν•˜κΈ° λ³Έλ¬Έ

Algorithm

[C++/ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€] 블둝 μ΄λ™ν•˜κΈ°

bba_dda 2021. 1. 18. 17:57
λ°˜μ‘ν˜•

문제 μ„€λͺ…

λ‘œλ΄‡κ°œλ°œμž λ¬΄μ§€λŠ” ν•œ 달 μ•žμœΌλ‘œ λ‹€κ°€μ˜¨ μΉ΄μΉ΄μ˜€λ°° λ‘œλ΄‡κ²½μ§„λŒ€νšŒμ— μΆœν’ˆν•  λ‘œλ΄‡μ„ μ€€λΉ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ€€λΉ„ 쀑인 λ‘œλ΄‡μ€ 2 x 1 ν¬κΈ°μ˜ λ‘œλ΄‡μœΌλ‘œ λ¬΄μ§€λŠ” 0κ³Ό 1둜 이루어진 N x N ν¬κΈ°μ˜ μ§€λ„μ—μ„œ 2 x 1 ν¬κΈ°μΈ λ‘œλ΄‡μ„ 움직여 (N, N) μœ„μΉ˜κΉŒμ§€ 이동 ν•  수 μžˆλ„λ‘ ν”„λ‘œκ·Έλž˜λ°μ„ ν•˜λ €κ³  ν•©λ‹ˆλ‹€. λ‘œλ΄‡μ΄ μ΄λ™ν•˜λŠ” μ§€λ„λŠ” κ°€μž₯ μ™Όμͺ½, μƒλ‹¨μ˜ μ’Œν‘œλ₯Ό (1, 1)둜 ν•˜λ©° 지도 내에 ν‘œμ‹œλœ 숫자 0은 λΉˆμΉΈμ„ 1은 벽을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. λ‘œλ΄‡μ€ 벽이 μžˆλŠ” μΉΈ λ˜λŠ” 지도 λ°–μœΌλ‘œλŠ” 이동할 수 μ—†μŠ΅λ‹ˆλ‹€. λ‘œλ΄‡μ€ μ²˜μŒμ— μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 μ’Œν‘œ (1, 1) μœ„μΉ˜μ—μ„œ κ°€λ‘œλ°©ν–₯으둜 λ†“μ—¬μžˆλŠ” μƒνƒœλ‘œ μ‹œμž‘ν•˜λ©°, μ•žλ’€ ꡬ뢄없이 움직일 수 μžˆμŠ΅λ‹ˆλ‹€.

λ‘œλ΄‡μ΄ 움직일 λ•ŒλŠ” ν˜„μž¬ λ†“μ—¬μžˆλŠ” μƒνƒœλ₯Ό μœ μ§€ν•˜λ©΄μ„œ μ΄λ™ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μœ„ κ·Έλ¦Όμ—μ„œ 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ μ΄λ™ν•œλ‹€λ©΄ (1, 2), (1, 3) λ‘ 칸을 μ°¨μ§€ν•˜κ²Œ 되며, μ•„λž˜λ‘œ μ΄λ™ν•œλ‹€λ©΄ (2, 1), (2, 2) λ‘ 칸을 μ°¨μ§€ν•˜κ²Œ λ©λ‹ˆλ‹€. λ‘œλ΄‡μ΄ μ°¨μ§€ν•˜λŠ” 두 μΉΈ 쀑 μ–΄λŠ ν•œ 칸이라도 (N, N) μœ„μΉ˜μ— λ„μ°©ν•˜λ©΄ λ©λ‹ˆλ‹€.

λ‘œλ΄‡μ€ λ‹€μŒκ³Ό 같이 쑰건에 따라 νšŒμ „μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

μœ„ κ·Έλ¦Όκ³Ό 같이 λ‘œλ΄‡μ€ 90도씩 νšŒμ „ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 단, λ‘œλ΄‡μ΄ μ°¨μ§€ν•˜λŠ” 두 μΉΈ 쀑, μ–΄λŠ 칸이든 좕이 될 수 μžˆμ§€λ§Œ, νšŒμ „ν•˜λŠ” λ°©ν–₯(좕이 λ˜λŠ” μΉΈμœΌλ‘œλΆ€ν„° λŒ€κ°μ„  λ°©ν–₯에 μžˆλŠ” μΉΈ)μ—λŠ” 벽이 μ—†μ–΄μ•Ό ν•©λ‹ˆλ‹€. λ‘œλ΄‡μ΄ ν•œ μΉΈ μ΄λ™ν•˜κ±°λ‚˜ 90도 νšŒμ „ν•˜λŠ” λ°λŠ” κ±Έλ¦¬λŠ” μ‹œκ°„μ€ μ •ν™•νžˆ 1초 μž…λ‹ˆλ‹€.

0κ³Ό 1둜 이루어진 지도인 boardκ°€ μ£Όμ–΄μ§ˆ λ•Œ, λ‘œλ΄‡μ΄ (N, N) μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λŠ”λ° ν•„μš”ν•œ μ΅œμ†Œ μ‹œκ°„μ„ return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄μ£Όμ„Έμš”.

μ œν•œμ‚¬ν•­

  • board의 ν•œ λ³€μ˜ κΈΈμ΄λŠ” 5 이상 100 μ΄ν•˜μž…λ‹ˆλ‹€.
  • board의 μ›μ†ŒλŠ” 0 λ˜λŠ” 1μž…λ‹ˆλ‹€.
  • λ‘œλ΄‡μ΄ μ²˜μŒμ— 놓여 μžˆλŠ” μΉΈ (1, 1), (1, 2)λŠ” 항상 0으둜 μ£Όμ–΄μ§‘λ‹ˆλ‹€.
  • λ‘œλ΄‡μ΄ 항상 λͺ©μ μ§€μ— 도착할 수 μžˆλŠ” 경우만 μž…λ ₯으둜 μ£Όμ–΄μ§‘λ‹ˆλ‹€.

μž…μΆœλ ₯ 예

board result
[[0, 0, 0, 1, 1],[0, 0, 0, 1, 0],[0, 1, 0, 1, 1],[1, 1, 0, 0, 1],[0, 0, 0, 0, 0]] 7

λ¬Έμ œμ— 주어진 μ˜ˆμ‹œμ™€ κ°™μŠ΅λ‹ˆλ‹€.
λ‘œλ΄‡μ΄ 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ 이동 ν›„, (1, 3) 칸을 μΆ•μœΌλ‘œ λ°˜μ‹œκ³„ λ°©ν–₯으둜 90도 νšŒμ „ν•©λ‹ˆλ‹€. λ‹€μ‹œ, μ•„λž˜μͺ½μœΌλ‘œ 3μΉΈ μ΄λ™ν•˜λ©΄ λ‘œλ΄‡μ€ (4, 3), (5, 3) 두 칸을 μ°¨μ§€ν•˜κ²Œ λ©λ‹ˆλ‹€. 이제 (5, 3)을 μΆ•μœΌλ‘œ μ‹œκ³„ λ°©ν–₯으둜 90도 νšŒμ „ ν›„, 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ μ΄λ™ν•˜λ©΄ (N, N)에 λ„μ°©ν•©λ‹ˆλ‹€. λ”°λΌμ„œ λͺ©μ μ§€μ— λ„λ‹¬ν•˜κΈ°κΉŒμ§€ μ΅œμ†Œ 7μ΄ˆκ°€ κ±Έλ¦½λ‹ˆλ‹€.

 

풀이

ν’€λ©΄μ„œ λŠλ‚€ μ£Όμ˜μ‚¬ν•­

1. λ‘œλ΄‡μ€ ν˜„μž¬ λ†“μ—¬μžˆλŠ” λ°©ν–₯에 관계없이 μƒν•˜μ’Œμš°λ‘œ 움직일 수 μžˆλ‹€.

μ²˜μŒμ— κ°€λ‘œλ‘œ λ†“μ—¬μžˆμœΌλ©΄ 쒌,우, μ„Έλ‘œλ‘œ λ†“μ—¬μžˆμœΌλ©΄ μœ„,μ•„λž˜ 둜만 움직일 수 μžˆλŠ”μ€„ μ•Œκ³  코딩을 μ§„ν–‰ν–ˆλ‹€. ν•˜μ§€λ§Œ λ‘œλ΄‡μ€ μ–Έμ œλ“ μ§€ (벽만 μ—†μœΌλ©΄) μƒν•˜μ’Œμš°λ‘œ λͺ¨λ‘ 움직일 수 μžˆλ‹€! 

 

2. νšŒμ „ν•  λ•Œ 좕에 λ”°λ₯Έ 경우의 수 λ‚˜λ‰¨.

예λ₯Όλ“€μ–΄ λ‘œλ΄‡μ΄ μ„Έλ‘œλ°©ν–₯ 일 λ•Œ, μ™Ό/였 두 κ°€μ§€λ‘œ νšŒμ „κ°€λŠ₯ν•˜λ‹€κ³  μƒκ°ν•˜κΈ° μ‰½μ§€λ§Œ, μ–΄λŠ 칸이 좕이 λ˜λŠλƒμ— 따라 경우의 μˆ˜κ°€ λ‚˜λ‰œλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. 

λ”°λΌμ„œ, μœ„ 칸이 μΆ• - μ™Ό/였, μ•„λž˜ 칸이 μΆ• - μ™Ό/였 -> 4κ°€μ§€λ‘œ λ‚˜λ‰œλ‹€.

λ‘œλ΄‡μ΄ κ°€λ‘œλ°©ν–₯일 λ•Œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ μ μš©λœλ‹€. 

 

3. μ²˜μŒλΆ€ν„° λ„ˆλ¬΄ μ–΄λ ΅κ²Œ μƒκ°ν•˜μ§€ 말기

λ‘œλ΄‡μ΄ 2칸을 μ°¨μ§€ν•˜κ³ , 심지어 νšŒμ „κΉŒμ§€ λ“€μ–΄κ°€λ³΄μ—¬μ„œ 맀우 μ–΄λ ΅κ²Œ λ³΄μ˜€λ‹€. (μ‹€μ œλ‘œ 어렡기도 ν–ˆμ§€λ§Œ..) ν•˜μ§€λ§Œ bfsλ₯Ό 쑰금 λ³€ν˜•ν•˜λ©΄ ν’€ 수 μžˆλŠ” λ¬Έμ œμ˜€λ‹€. 쑰건이 λ§Žλ‹€κ³  μ²˜μŒλΆ€ν„° 겁먹을 ν•„μš”λŠ” 없을 것 κ°™λ‹€.

 

λ‚΄μš©

1. λ‘œλ΄‡ ꡬ쑰체(struct) 이용

  • time
    • λ‘œλ΄‡μ΄ ν•΄λ‹Ή μœ„μΉ˜λ‘œ 올 λ•Œ κΉŒμ§€ κ±Έλ¦° μ‹œκ°„
  • x, y 
    • λ‘œλ΄‡μ˜ μ’Œν‘œ, λ‘œλ΄‡μ΄ κ°€λ‘œμ™€ μ„Έλ‘œμΌ λ•Œ 각각 μ•„λž˜ 사진속 칸을 x,y둜 μ„€μ •

  • type 
    • κ°€λ‘œ = 0, μ„Έλ‘œ = 1

2. bfs 이용

μ’…λ£Œ 쑰건을 λ§Œμ‘±ν•  λ•Œ κΉŒμ§€ νμ—μ„œ ν•˜λ‚˜λ₯Ό κΊΌλ‚΄κ³ ,  ν•΄λ‹Ή μœ„μΉ˜μ—μ„œ κ°€λŠ₯ν•œ λ‹€μŒ μœ„μΉ˜λ“€μ„ λͺ¨λ‘ λ„£λŠ” λ°©μ‹μœΌλ‘œ 진행

μ’…λ£Œ 쑰건 : λ‘œλ΄‡μ΄ (n-1,n-1)에 μœ„μΉ˜ν–ˆμ„ λ•Œ. 

μ½”λ“œ

μ²˜μŒμ— bfs둜 풀어야지 ν•˜λ‹€κ°€, μ½”λ“œλ₯Ό λ‹€ μ§œκ³ λ³΄λ‹ˆ dfs둜 ν’€κ³  μžˆμ—ˆλ‹€λŠ” 사싀을 κΉ¨λ‹¬μ•˜λ‹€.. μ²˜μŒλΆ€ν„° λ‹€μ‹œ μ‹œμž‘..

#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
struct robot {
	int time;
	int x;
	int y;
	int type; // 0 : κ°€λ‘œ, 1 : μ„Έλ‘œ
};
bool check(int x, int y, int type);
int visit[101][101][2]; // 0 : κ°€λ‘œ, 1 : μ„Έλ‘œ
int dx[] = { -1, 1, 0, 0 }; //상 ν•˜ 쒌 우
int dy[] = { 0, 0, -1, 1 };
vector<vector<int> > table;


bool check(int x, int y, int type) { // λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜κ±°λ‚˜, 벽에 λΆ€λ”ͺ히면 false
	int N = table.size();
	if (type == 0) {//κ°€λ‘œ
		if (x < 0 || y < 0 || x >= N || y + 1 >= N) return false;
		if (table[x][y] || table[x][y + 1]) return false;
	}
	else {//μ„Έλ‘œ
		if (x < 0 || y < 0 || x + 1 >= N || y >= N) return false;
		if (table[x][y] || table[x + 1][y]) return false;
	}
	return true;
}
int solution(vector<vector<int>> board) {
	int answer = 0, N = board.size(); 
	table = board;

	memset(visit, 0, sizeof(visit));

	queue<robot> q;
	q.push({ 0, 0, 0, 0 });
	while (!q.empty()) {
		robot now = q.front(); 
		q.pop();
		if ((now.type == 0 && now.x == N - 1 && now.y == N - 2) || (now.type == 1 && now.x == N - 2 && now.y == N - 1)) {
			return now.time;
		}

		for (int i = 0; i < 4; i++) { // μƒν•˜μ’Œμš° 이동
			int nx = now.x + dx[i];
			int ny = now.y + dy[i];
			if (!check(nx, ny, now.type) || visit[nx][ny][now.type]) continue; //이전에 λ°©λ¬Έν•œ 적 있으면 κ±΄λ„ˆλ›°κΈ°
			visit[nx][ny][now.type] = 1;
			q.push({ now.time + 1, nx, ny, now.type });
		}

		//μ—¬κΈ°λΆ€ν„° νšŒμ „
		if (now.type == 0) { //κ°€λ‘œ
			//였λ₯Έμͺ½ 칸이 μΆ•
			if (now.x + 1 <= N - 1 && !table[now.x + 1][now.y] && !table[now.x + 1][now.y + 1] && !visit[now.x][now.y + 1][1]) {
				q.push({ now.time + 1, now.x, now.y + 1, 1 });
			}
			if (now.x - 1 >= 0 && !table[now.x - 1][now.y] && !table[now.x - 1][now.y + 1] && !visit[now.x - 1][now.y + 1][1]) {
				q.push({ now.time + 1, now.x - 1, now.y + 1, 1 });
			}
			//μ™Όμͺ½ 칸이 μΆ•
			if (now.x + 1 <= N - 1 && !table[now.x + 1][now.y + 1] && !table[now.x + 1][now.y] && !visit[now.x][now.y][1]) {
				q.push({ now.time + 1, now.x, now.y, 1 });
			}
			if (now.x - 1 >= 0 && !table[now.x - 1][now.y + 1] && !table[now.x - 1][now.y] && !visit[now.x - 1][now.y][1]) {
				q.push({ now.time + 1, now.x - 1, now.y, 1 });
			}
		}
		else { //μ„Έλ‘œ
		    //μ•„λž˜μΉΈμ΄ μΆ•
			if (now.y - 1 >= 0 && !table[now.x][now.y - 1] && !table[now.x + 1][now.y - 1] && !visit[now.x + 1][now.y - 1][0]) {
				q.push({ now.time + 1, now.x + 1, now.y - 1, 0 });
			}
			if (now.y + 1 <= N - 1 && !table[now.x][now.y + 1] && !table[now.x + 1][now.y + 1] && !visit[now.x + 1][now.y][0]) {
				q.push({ now.time + 1, now.x + 1, now.y, 0 });
			}
			//μœ„ 칸이 μΆ•
			if (now.y - 1 >= 0 && !table[now.x + 1][now.y - 1] && !table[now.x][now.y - 1] && !visit[now.x][now.y - 1][0]) {
				q.push({ now.time + 1, now.x, now.y - 1, 0 });
			}
			if (now.y + 1 <= N - 1 && !table[now.x + 1][now.y + 1] && !table[now.x][now.y + 1] && !visit[now.x][now.y][0]) {
				q.push({ now.time + 1, now.x, now.y, 0 });
			}
		}
	}
}
λ°˜μ‘ν˜•