🌞Algorithm/🔥Baekjoon

[Baekjoon] 9019_DSLR

뿌야._. 2022. 12. 23. 10:25

Gold IV

문제(출처: https://www.acmicpc.net/problem/9019)

< DSLR >

 

문제 풀이

 

bfs를 활용하여 D S L R 명령어를 실행한다. 그 결과가 B가 되었다면 바로 종료해 준다.

결과가 B가 아니라면 계속해서 queue에 넣어주며 결과가 나올 때까지 실행해 준다.

 

 

 - my solution (Java)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class _9019_ {
	static int A,B;
	static String result="";
	static Queue<Integer>queue;
	static Queue<String>cmd;
	static boolean check[];

	public static void main(String[] args) throws IOException {
		BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		
		int T=Integer.parseInt(bf.readLine()); //테스트 케이스
		queue=new LinkedList<>();
		cmd=new LinkedList<>();
		
		for(int i=0; i<T; i++) {
			st=new StringTokenizer(bf.readLine());
			A=Integer.parseInt(st.nextToken());
			B=Integer.parseInt(st.nextToken());
			result="";
			queue.clear();
			cmd.clear();
			check=new boolean[10000];
			search();
			System.out.println(result);
		}
	}
	private static int D(int num) {
		return (num*2)%10000;
	}
	
	private static int S(int num) {
		if(num==0) return 9999;
		else return num-1;
	}
	
	private static int L(int num) { 
		int n=num%1000;
		int temp=num/1000;
		return (n*10)+temp;
	}
	
	private static int R(int num) {
		int n=num/10;
		int temp=num%10;
		return (temp*1000)+n;
	}

	private static void search() {
		queue.add(A);
		check[A]=true;
		cmd.add("");
		
		while(!queue.isEmpty()) {
			int n=queue.poll();
			String line=cmd.poll();

			int num=D(n);
			if(num==B) {
				result=line+"D";
				break;
			}
			else if(!check[num]){
				check[num]=true;
				queue.add(num);
				cmd.add(line+"D");
			}
			num=S(n);
			if(num==B) {
				result=line+"S";
				break;
			}
			else if(!check[num]){
				check[num]=true;
				queue.add(num);
				cmd.add(line+"S");
			}

			num=L(n);
			if(num==B) {
				result=line+"L";
				break;
			}
			else if(!check[num]){
				check[num]=true;
				queue.add(num);
				cmd.add(line+"L");
			}
			num=R(n);
			if(num==B) {
				result=line+"R";
				break;
			}
			else if(!check[num]){
				check[num]=true;
				queue.add(num);
				cmd.add(line+"R");
			}
			if(result!="")break;
		}
	}
}

 

  • Main
    • queue: 레지스터의 값 저장
    • cmd: 현제까지 실행한 명령어
    • check: 레지스터 중복 확인
  • D : 2배로 바꾼 후 10000으로 나눈 나머지를 반환
  • S : 레지스터 값이 0 이면 9999 반환 , 0이 아니면 1 뺀 값을 반환
  • L : 자릿수를 왼편으로 회전시키는 방법은 몫 연산을 통해 첫째 자리를 저장, 나머지 연산을 통해 세 자리를 저장한 후 세 자리*10을 한 후 몫을 더해준다. (세 자리*10을 하면 4자리로 맞춰지기 때문이다)
  • R : 자릿수를 오른편으로 회전시키는 방법은 몫 연산을 통해 세 자리를 저장, 나머지 연산을 통해 마지막자리를 저장한 후 마지막 자리를 첫 번째 자리로 만들기 위해 1000을 곱한 후 나머지 세 자리를 더해준다.
  • search
    • queue, check, cmd에 초기값을 넣어준다
    • queue가 빌 때까지 반복 -> 각 queue에서 하나씩 뽑은 후 연산을 수행해 준다. D, S, L, R 명령을 실행 후 그 값이 B와 같다면 종료해 준다. B와 같지 않다면 중복된 레지스터 값인지 확인 후 중복된 값이 아니라면 중복 check, queue, cmd에 넣어준다.

생각🤔

 

힘들었다!!!

 

처음에는 R와 L 연산 때문에 int로 받은 값을 string으로 바꿔주었으며, 중복 check를 위해 hashset을 사용했었다. 하지만 계속해서 시간 초과와 메모리 초과가 발생하였다. 여기서 큰 이유는 int를 string으로 계속해서 바꿔주는 연산 때문에 시간초과가 발생한다고 생각하였다. 그래서 조금 힌트를 얻고 생각해본 결과 L과 R을 int인 상태에서 해결할 수 있었다.

 

그 후에는 메모리 초과가 문제였다. 이 부분은 잘 몰라서 찾아보니 queue 초기화와 중복 check 때문인 것 같았다. 그래서 queue를 clear를 해주었으며, 레지스터 값이 0 이상 10000 미만으로 정해져 있으므로 배열을 통해 중복 확인을 해주는 것으로 코드를 수정하였다. 그 결과 통과할 수 있었다.

 


'🌞Algorithm > 🔥Baekjoon' 카테고리의 다른 글

[Baekjoon] 13565_침투  (1) 2022.12.27
[Baekjoon] 16197_두 동전  (0) 2022.12.26
[Baekjoon] 12919_A와 B 2  (0) 2022.12.22
[Baekjoon] 15644_구슬 탈출 3  (0) 2022.12.21
[Baekjoon] 13459_구슬 탈출  (0) 2022.12.20