13460번: 구슬 탈출 2
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'
www.acmicpc.net
DP문제집을 풀다가 재미있어 보이는 문제가 있어서 풀기시작했다.
풀면 풀수록 생각할 것이 더 생기는 문제였다.
결국 풀기는 했지만 실행시간이 엄청 오래걸렸다...
(이전에 이동한 위치를 또 갈수있게 만들어서 실행 횟수가 엄청 늘어났다)
그래서 이전에 이동한 위치를 visited에 저장해서 다시한번 풀어봐야겠다.
내가 푼 방법
1. 빨강구슬과 파랑구슬은 겹치면 안된다.
( 둘 다 (2,2) 지점으로 간다면 먼저 도착한 구슬(2,2) 옆에 다른 구슬이 위치한다 (2,3) )
2. 한번 실행에 파랑구슬과 빨강구슬이 같이 구멍에 들어갔다면 실패
3. 실행횟수는 10번을 넘지않는다.
4. 큐에는 빨간구슬 위치와 파란구슬 위치를 같이 저장해준다.
구슬이 구멍에 도착하면 해당 색깔 구슬 위치를 -1,-1로 지정해줬다.
( 지금 생각해보면 매우 별로인 방법이다.
후에 같은 좌표를 가지않기 위해 visited를 사용하는데 -1좌표때문에 if문을 더 써줘야한다. 아래 링크)
[백준] 13460 - 구슬 탈출2 Re (java)
[백준] 13460 - 구슬 탈출2 (java) 13460번: 구슬 탈출 2 첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의
dwc04112.tistory.com
1번을 만족시키기 위해 구슬 굴리는 순서를 정해주었다.
i는 0~3이고 순서대로 상 하 좌 우이다.
만약 (1,1) 빨간구슬과 (2,1)파란구슬을 아래로 굴린다고 생각해보자
이러면 파란색 구슬이 먼저 (3,1)에 도착하고 그 뒤(2,1)에 빨간구슬이 도착할것이다.
즉 굴리는 방향 i 에 따라 어떤구슬이 먼저 굴러가는지 정해줘야한다.
if(i==0){
// 순서정하기
if(temp.redR < temp.blueR) {
data = redMove(temp , i);
data = blueMove(data , i);
}else{
data = blueMove(temp , i);
data = redMove(data , i);
}
}else if(i==1){
if(temp.redR < temp.blueR) {
data = blueMove(temp , i);
data = redMove(data , i);
}else{
data = redMove(temp , i);
data = blueMove(data , i);
}
}else if(i==2){
if(temp.redC < temp.blueC) {
data = redMove(temp , i);
data = blueMove(data , i);
}else{
data = blueMove(temp , i);
data = redMove(data , i);
}
}else {
if(temp.redC < temp.blueC) {
data = blueMove(temp , i);
data = redMove(data , i);
}else{
data = redMove(temp , i);
data = blueMove(data , i);
}
}
2번 두 구슬이 같이 구멍에 들어간다면 실패
빨간 구슬만 구멍에 들어가야지 답을 갱신해준다.
if(data.redR==-1 && data.blueR!=-1){
if(res==-1) res = temp.count+1;
else if(res > (temp.count+1)) res = temp.count+1;
}
그리고 구슬 굴리기
#을 만나면 변경하기 전 위치를 리턴하고
O를 만나면 해당 구슬 좌표를 -1로 보낸다
만약 이동하려는 위치가 다른 색 구슬 위치와 같으면 이동하기 전 위치를 보낸다.
( 1.번을 만족시키기 위해 )
private static Node redMove(Node node , int i) {
int nr = node.redR + D[i][0];
int nc = node.redC + D[i][1];
if(Board[nr][nc] == '#') return node;
if(node.blueR!=-1 && node.blueC!=-1)
if( visited[nr][nc][node.blueR][node.blueC]) return node;
if(Board[nr][nc] == 'O') {
return new Node(-1,-1,node.blueR,node.blueC, node.count);
}
if(nr == node.blueR && nc == node.blueC) return node;
return redMove(new Node(nr,nc,node.blueR,node.blueC, node.count),i);
}
전체코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int N,M;
static char[][] Board;
static int[][] D = {{-1,0},{1,0},{0,-1},{0,1}};
static Queue<Node> queue = new LinkedList<>();
static int res = -1;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
Board = new char[N+1][M+1];
for (int i = 0; i < N; i++) {
Board[i] = br.readLine().toCharArray();
}
int rRow=0,rCol=0,bRow=0,bCol=0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if(Board[i][j] == 'R') {
Board[i][j] = '.';
rRow = i;
rCol = j;
}
if(Board[i][j] == 'B') {
Board[i][j] = '.';
bRow = i;
bCol = j;
}
}
}
queue.add(new Node(rRow,rCol,bRow,bCol,0));
play();
}
private static void play() {
int loop = 0;
while(!queue.isEmpty()){
Node temp = queue.remove();
if(temp.count==10) continue;
for (int i = 0; i < 4; i++) {
// i 순서대로 상 하 좌 우
// {{-1,0},{1,0},{0,-1},{0,1}};
Node data;
if(temp.redR==-1) continue;
if(temp.blueR==-1) continue;
if(i==0){
// 순서정하기
if(temp.redR < temp.blueR) {
data = redMove(temp , i);
data = blueMove(data , i);
}else{
data = blueMove(temp , i);
data = redMove(data , i);
}
}else if(i==1){
if(temp.redR < temp.blueR) {
data = blueMove(temp , i);
data = redMove(data , i);
}else{
data = redMove(temp , i);
data = blueMove(data , i);
}
}else if(i==2){
if(temp.redC < temp.blueC) {
data = redMove(temp , i);
data = blueMove(data , i);
}else{
data = blueMove(temp , i);
data = redMove(data , i);
}
}else {
if(temp.redC < temp.blueC) {
data = blueMove(temp , i);
data = redMove(data , i);
}else{
data = redMove(temp , i);
data = blueMove(data , i);
}
}
if(data.redR==-1 && data.blueR!=-1){
if(res==-1) res = temp.count+1;
else if(res > (temp.count+1)) res = temp.count+1;
}
queue.add(new Node(data.redR, data.redC, data.blueR, data.blueC, temp.count + 1));
}
}
System.out.println(res);
}
private static Node redMove(Node node , int i) {
int nr = node.redR + D[i][0];
int nc = node.redC + D[i][1];
if(Board[nr][nc] == '#') return node;
if(Board[nr][nc] == 'O') {
return new Node(-1,-1,node.blueR,node.blueC, node.count);
}
if(nr == node.blueR && nc == node.blueC) return node;
return redMove(new Node(nr,nc,node.blueR,node.blueC, node.count),i);
}
private static Node blueMove(Node node , int i) {
int nr = node.blueR + D[i][0];
int nc = node.blueC + D[i][1];
if(Board[nr][nc] == '#') return node;
if(Board[nr][nc] == 'O') {
return new Node(node.redR, node.redC, -1,-1, node.count);
}
if(nr == node.redR && nc == node.redC) return node;
return blueMove(new Node(node.redR, node.redC, nr,nc, node.count),i);
}
static class Node{
int redR,redC;
int blueR, blueC;
int count;
Node(int rr, int rc, int br, int bc, int c){
redR = rr;
redC = rc;
blueR = br;
blueC = bc;
count = c;
}
}
}
'연습문제 > JAVA' 카테고리의 다른 글
[백준] 9095 - 1,2,3더하기 (java) (0) | 2022.09.20 |
---|---|
[백준] 13460 - 구슬 탈출2 Re (java) (0) | 2022.09.19 |
[백준] 2294 - 동전 2 (java) (0) | 2022.09.14 |
[백준] 11052 - 카드 구매하기 (java) (0) | 2022.09.14 |
[백준 java] 1912 - 연속합 (0) | 2022.09.13 |