[백준/바킹독] 0309 시뮬레이션 3

OOING·2024년 3월 9일
0

백준+알고리즘 공부

목록 보기
59/75

오늘의 문제
13335 트럭
16985 Maaaaaaaaaze
14503 로봇 청소기

13335 트럭

코드

#include <bits/stdc++.h>
using namespace std;

int n, w, l;
int trucks[1002];

int main() {
	cin >> n >> w >> l;
	for (int i = 0; i < n; i++) cin >> trucks[i];

	queue<int> q;
	for (int i = 0; i < w; i++) q.push(0);

	int now_weight = 0, min_time = 0, i = 0;
	while (!q.empty()) {
		now_weight -= q.front();
		q.pop();
		if (now_weight + trucks[i] <= l) {
			if (i == n - 1) {
				min_time = min_time + w + 1;
				break;
			}
			q.push(trucks[i]);
			now_weight += trucks[i];
			++i;
		}
		else {
			q.push(0);
		}
		++min_time;
	}

	cout << min_time;
}

다리를 queue로 표현하여 트럭이 없는 경우 0, 트럭이 있는 경우 트럭의 무게를 큐에 넣는다.
시간이 흐름에 따라 트럭이 다리에서 한 칸씩 이동하므로 q.pop() 으로 전진을 표현.
이후 현재 무게에 따라 새로 트럭이 올라오는지 아닌지 결정하여 0 또는 트럭의 무게를 q에 삽입.

16985 Maaaaaaaaaze

코드

#include <bits/stdc++.h>
using namespace std;

int maze[5][5][5], tmp_maze[5][5][5];
int dx[6] = { 1, -1, 0, 0, 0, 0 };
int dy[6] = { 0, 0, 1, -1, 0, 0, };
int dz[6] = { 0, 0, 0, 0, 1, -1 };

// 현재 좌표가 미로 내부 && 이동할 수 있는 칸인지 확인
bool check(int x, int y, int z) {
	return x >= 0 && x < 5 && y >= 0 && y < 5 && z >= 0 && z < 5 && tmp_maze[z][x][y] == 1;
}

// 미로를 시계방향으로 90도 회전
void rotate(int b) {
	int tmp[5][5] = {};
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			tmp[i][j] = tmp_maze[b][4 - j][i];
		}
	}
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			tmp_maze[b][i][j] = tmp[i][j];
		}
	}
}

void copy_board(int a, int b) {
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			tmp_maze[b][i][j] = maze[a][i][j];
		}
	}
}

// 현재 3차원 미로에서 탈출구(maze[4][4][4])까지의 최단 거리 구하기
// 자유롭게 회전 가능하므로 1024(4*4*4*4*4)가지의 모든 경우에서 계산
int solve() {
	int min_dist = 100000;

	for (int a = 0; a < 4; a++) {
		for (int b = 0; b < 4; b++) {
			for (int c = 0; c < 4; c++) {
				for (int d = 0; d < 4; d++) {
					for (int e = 0; e < 4; e++) {
						rotate(0);
						if (tmp_maze[0][0][0] == 0) continue;
                        
						// 최단 거리 찾기(bfS)
						queue<tuple<int, int, int>> q; // z, x, y
						int dist[5][5][5];
						fill_n(&dist[0][0][0], 125, -1);
						q.push({ 0, 0, 0 });
						dist[0][0][0] = 0;

						while (!q.empty()) {
							if (dist[4][4][4] != -1) break;

							int nowz = get<0>(q.front());
							int nowx = get<1>(q.front());
							int nowy = get<2>(q.front());
							q.pop();

							for (int i = 0; i < 6; i++) {
								int nextx = nowx + dx[i];
								int nexty = nowy + dy[i];
								int nextz = nowz + dz[i];

								if (check(nextx, nexty, nextz) && dist[nextz][nextx][nexty] == -1) {
									q.push({ nextz, nextx, nexty });
									dist[nextz][nextx][nexty] = dist[nowz][nowx][nowy] + 1;
								}
							}
						}
						if (dist[4][4][4] == -1) continue;
						min_dist = min_dist > dist[4][4][4] ? dist[4][4][4] : min_dist;
					}
					rotate(1);
				}
				rotate(2);
			}
			rotate(3);
		}
		rotate(4);
	}
		
	return min_dist;
}

// 3차원 미로의 순서 변경 (5!)
int change() {
	int min_dist = 100000;
	int seq[5] = { 0, 1, 2, 3, 4 };
	do {
		for (int i = 0; i < 5; i++) {
			copy_board(seq[i], i);
		}
		int v = solve();
		min_dist = min_dist > v ? v : min_dist;
	} while (next_permutation(seq, seq + 5));
	return min_dist;
}


int main() {
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			for (int k = 0; k < 5; k++) {
				cin >> maze[i][j][k];
			}
		}
	}
	int dist = change();
	cout << (dist == 100000 ? -1 : dist);
}

3차원 미로이기 때문에 동서남북 이동 + 상하 이동이라 dz를 추가해 이동 배열의 크기가 6이 되었다.
코드의 길이가 길지만, 그렇게 어렵지는 않은 문제인 것 같다.
모든 경우를 계산했을 때 2초의 시간 내에 통과할 수 있을 것 같아 5중 for문을 쓸 수 있었다.......

14503 로봇 청소기

코드

#include <bits/stdc++.h>
using namespace std;

int n, m, r, c, d;
int room[52][52];
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, 1, 0, -1 };

void clean() {
	int nowx = r, nowy = c, dir = d;
	while (1) {
		if (room[nowx][nowy] == 0) room[nowx][nowy] = 2;
		bool blank = false;
		for (int i = 0; i < 4; i++) {
			if (room[nowx + dx[i]][nowy + dy[i]] == 0) {
				blank = 1;
				break;
			}
		}
		if (blank) {
			do {
				dir = (dir + 3) % 4;
				if(room[nowx + dx[dir]][nowy + dy[dir]] == 0) break;
			} while (1);
			nowx += dx[dir];
			nowy += dy[dir];
			continue;
		}
		else {
			int tmp = (dir + 2) % 4;
			if (room[nowx + dx[tmp]][nowy + dy[tmp]] == 1) return;
			else{
				nowx += dx[tmp];
				nowy += dy[tmp];
				continue;
			}
		}

	}
}

int main() {
	cin >> n >> m >> r >> c >> d;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> room[i][j];
		}
	}
	clean();
	int num = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (room[i][j] == 2) ++num;
		}
	}
	cout << num;
}

문제의 조건이 조금 이해하기 힘들어서 질문 게시판에 있는 질문을 교체해 달라는 게시글을 참고했다.
room[x][y]가 0인 경우 청소 전, 1인 경우 벽, 2인 경우 청소 후로 나타냈다.
조건을 그~대로 코드로 작성하여 쉽게 해결할 수 있었다.

profile
HICE 19

0개의 댓글