일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- ddd
- http 완벽가이드
- go
- flask
- 백준 12761
- 트리 순회
- domain driven develop
- golang struct
- 하둡
- 몽고디비 렘
- 우분투
- MongoDB Realm
- 백준
- 백준 파이썬
- 백준 사이트
- golang
- 정렬
- 자바 디자인 패턴
- 자바 디자인패턴
- 백준 12761번
- 자바
- 고 배열
- String 함수
- 파이썬
- 도메인 주도 개발
- http 개념
- 도메인 주도 개발 시작하기
- 12761번 돌다리
- hadoop
- 12761 돌다리
- Today
- Total
개발바닥
BOJ_15653 [ 구슬 탈출4 ] 본문
문제
https://www.acmicpc.net/problem/15653
15653번: 구슬 탈출 4
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'
www.acmicpc.net
문제 해결 방법
완탐을 하면 문제를 해결할 수 있다.
시키는데로 구현만 하면 되는 문제이지만 조건이 까다로워서 한부분이라도 놓치면 시간을 많이 소비하게 되므로
이런 문제는 코드를 구현하기 전에 설계를 꼼꼼하게 해야된다.
중복 탐색을 방지하기 위해서 4차원 체크 변수를 선언하였습니다.
check[빨간공 Y좌표][빨간공 X좌표][파란공 Y좌표][파란공 X좌표]
해당 좌표에서 상,하,좌,우 로 이동시키고 난 후
총 4가지 조건을 체크하였습니다.
1. 빨간공 , 파란공이 겹친 경우
1-1. 둘다 구멍에 빠진 경우
1-2. 둘다 빈 공간에 겹친 경우 ( 각 공에 시작 위치에 따라서 한 칸 되돌린다.)
2. 빨간공이 구멍에 빠지고 파란공이 안빠진 경우
3. 파란공이 구멍에 빠지고 빨간공이 안빠진 경우
4. 빨간공,파란공 둘 다 빈 공간에 있는 경우
그리고 문제를 풀기 위해서 꼭 필요한 로직을 함수화 했습니다.
1. 공을 특정 방향으로 못움직일때까지 이동하는 함수
2. 공 좌표를 다음 좌표로 계산해주는 함수
3. 공이 똑같은 좌표에 있을 때 어떤 볼을 한 칸 덜 이동해야되는지 체크해주는 함수
4. bfs 함수
이렇게 전체적인 시뮬레이션 문제를 잘게 쪼개서 문제를 접근하시면 조금 더 쉽게 해결하실 수 있습니다.
소스 코드 보기
https://github.com/jokerKwu/BOJ_Algorithm/blob/master/Brute%20force/BOJ_15653.cpp
jokerKwu/BOJ_Algorithm
Contribute to jokerKwu/BOJ_Algorithm development by creating an account on GitHub.
github.com
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define MAX 11
bool check[MAX][MAX][MAX][MAX]; //방향 좌표 빨 , 파
char board[MAX][MAX];
int m_xy[5][2] = { {0,0}, {0,1},{0,-1},{1,0},{-1,0} };
int N, M,answer = -1;
typedef struct {
int x;
int y;
}Point;
Point red_ball, blue_ball;
//좌표 이동시키는 함수
Point ballCalc(Point ball, int dir) {
Point next_ball = { ball.x + m_xy[dir][0],ball.y + m_xy[dir][1] };
if (next_ball.y < 0 || next_ball.x < 0 || next_ball.x >= M || next_ball.y >= N) return ball;
return next_ball;
}
//볼 계속 이동시키는 함수
Point ballMove(Point ball, int dir) {
Point next_ball, cur_ball = ball;
while (true) {
next_ball = ballCalc(cur_ball, dir);
//벽인 경우
if (board[next_ball.y][next_ball.x] == '#') {
next_ball = cur_ball;
break;
}
//홀인 경우
else if (board[next_ball.y][next_ball.x] == 'O') {
break;
}
//빈 경우
else {
cur_ball = next_ball;
}
}
return next_ball;
}
bool sameBallCheck(Point red, Point blue, int dir) {
//빨간공이 이동해야된다면 true
//파란공이 이동해야된다면 false
if (dir == 1) {
//아래
//빨간공이 아래 있다.
if (red.y > blue.y) return false; //파란공이 이동
else return true;
}
else if (dir == 2) {
//위
//빨간공이 아래 있다.
if (red.y > blue.y) return true;
else return false;
}
else if (dir == 3) {
//오
//빨간공이 오른쪽에 있다.
if (red.x > blue.x) return false; //파란공이 이동
else return true;
}
else if (dir == 4) {
//왼
//빨간공이 오른쪽에 있다.
if (red.x > blue.x) return true;
else return false;
}
}
void bfs() {
queue<pair<int,pair<Point,Point>>>q; //레드 블루,
q.push(make_pair(0,make_pair(red_ball, blue_ball)));
check[red_ball.y][red_ball.x][blue_ball.y][blue_ball.x] = 0;
while (!q.empty()) {
int cur_cnt = q.front().first;
Point cur_red = q.front().second.first;
Point cur_blue = q.front().second.second;
q.pop();
//레드, 블루 방향 이동시킨다..
for (int i = 1; i <= 4; i++) {
Point next_red = ballMove(cur_red, i);
Point next_blue = ballMove(cur_blue, i);
//빨강이랑 파랑이 겹치는 경우
if (next_red.x == next_blue.x && next_red.y == next_blue.y) {
//둘다 구멍에 빠진경우
if (board[next_red.y][next_red.x] == 'O') continue;
//이동한 방향에따라서 한칸 밀리게 한다.
if (sameBallCheck(cur_red, cur_blue, i) == false) {
//파란공이 밀려야된다.
next_blue = { next_blue.x - m_xy[i][0],next_blue.y - m_xy[i][1] };
}
else {
//빨간공이 밀려야된다.
next_red = { next_red.x - m_xy[i][0],next_red.y - m_xy[i][1] };
}
}
if (board[next_red.y][next_red.x] == 'O'&&board[next_blue.y][next_blue.x] == '.') {
//빨간공이 빠지고 파랑공은 안빠진경우
answer = cur_cnt + 1;
return;
}
else if (board[next_red.y][next_red.x] == '.' &&board[next_blue.y][next_blue.x] == 'O') {
//파란공 빠지고 빨간공 안빠진경우
continue;
}
else {
//둘다 빈 공간에 있으면 체크해서 이전에 방문했던건지 확인한다.
if (!check[next_red.y][next_red.x][next_blue.y][next_blue.x]) {
//cout << next_red.x << ' ' << next_red.y << ' ' << check[cur_red.y][cur_red.x][cur_blue.y][cur_blue.x] + 1 << '\n';
check[next_red.y][next_red.x][next_blue.y][next_blue.x] =true;
q.push(make_pair(cur_cnt+1,make_pair(next_red, next_blue)));
}
}
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> board[i][j];
if (board[i][j] == 'R') {
red_ball = { j,i };
board[i][j] = '.';
}
else if (board[i][j] == 'B') {
blue_ball = { j,i };
board[i][j] = '.';
}
}
}
bfs();
cout << answer << '\n';
return 0;
}
'[ Algorithm ] > [ BOJ ]' 카테고리의 다른 글
BOJ_9081 [ 단어 맞추기 ] (0) | 2023.03.12 |
---|---|
BOJ_5397 [ 키로거 ] (0) | 2023.03.04 |
BOJ_10942 [ 팰린드롬? ] (1) | 2020.06.09 |
BOJ_14442 [ 벽 부수고 이동하기 2 ] (0) | 2020.06.07 |
BOJ_16935 [ 배열 돌리기 3 ] (0) | 2020.05.07 |