[백준]1730번 판화 (JAVA)

U_U·2024년 9월 9일
0

알고리즘문제

목록 보기
10/11
post-thumbnail

문제 - 판화

문제 바로가기

문제

W대학교 미술대학 조소과에서는 지루한 목판화 작업을 하는 학생들을 돕기 위해 판화 기계를 제작하였다.

기계는 로봇 팔이 쥔 조각도를 상하좌우 네 방향으로 움직일 수 있는 구조로서, 조각도 아래에 목판을 놓으면 그 위에 선들을 자동으로 그어주는 기능을 가지고 있다.

목판에는 N2개의 점들이 일정한 간격으로 N행 N열의 격자모양을 이루며 찍혀있다. 처음 로봇의 조각도를 올려놓는 위치는 항상 이 점들 중 맨 왼쪽 맨 위의 꼭짓점이다.

로봇 팔을 움직이는 명령의 순서가 주어졌을 때, 목판 위에 패인 조각도의 혼적을 출력하는 프로그램을 작성하시오.

판화 기계는 작동 도중 로봇 팔이 격자 바깥으로 나가도록 하는 움직임 명령을 만나면, 무시하고 그 다음 명령을 진행한다.

입력

첫째 줄에 목판의 크기 N (2 ≤ N ≤ 10)이 주어진다. 행 열의 점들이 찍혀 있다는 의미이다. 둘째 줄에 로봇팔의 움직임이 한 줄로 공백 없이 입력된다. 위쪽으로 이동은 'U', 아래쪽으로 이동은 'D', 왼쪽으로 이동은 'L', 오른쪽으로 이동은 'R'로 표시된다. 로봇팔의 움직임을 나타내는 이 문자열의 길이는 최대 250이다.

출력

로봇팔이 지나지 않은 점은 '.'으로, 로봇팔이 수직 방향으로만 지난 점은 '|'으로, 로봇팔이 수평 방향으로만 지난 점은 '-'으로, 수직과 수평 방향 모두로 지난 점은 '+'로 표기하도록 한다. 네 문자의 ASCII 코드는 각각 46, 124, 45, 43이다.

예제 입력 1

5
DRDRRUU

예제 출력 1

|..|.
++.|.
.+-+.
.....
.....

예제 입력 2

4
RRRDDDDULL

예제 출력 2

---+
...|
.--+
...|

예제 입력 3

5
RRDDLLUURRDDLLUUR

예제 출력 3

+-+..
|.|..
+-+..
.....
.....

접근방식

조건을 세분화하여 각 조건에 맞는 case를 나눠 푸는 방식

이 문제같은 경우, 단순 구현(시뮬레이션)에 속하기 때문에 냅따 조건을 나눠 풀어야한다.

이 문제에서는 크게 두가지의 조건을 확인할 수 있다.

  • 명령어에 따른 이동 규칙
  • 이동한 자리의 흔적 규칙

명령어에 따른 이동 규칙

if(strs[i].equals("U")&& x+1 <N){ 
	...
}
else if(strs[i].equals("D")&& x-1 >=0) {
	...
}
else if(strs[i].equals("R") && y+1 <N) {
	...
}
else if(strs[i].equals("L") && y-1 >=0) {
	...
}

나 같은 경우에는 명령어와 함께 격자 밖으로 나갔는지 확인하는 if 문을 작성하였다.

이동한 자리의 흔적 규칙

처음 내가 짰던 코드는 아래와 같다.

	if(map[x][y] == (char) 45)
		map[x][y] = (char) 43;
	else map[x][y] = (char) 124;
				
	map[++x][y]= (char)124; // up, down, left, right에 따라 연산자 변경 

이렇게 냈을때 틀렸다고 나왔고 반례를 찾는데 오래걸렸다.

백준 질문 게시판에서 찾은 내가 놓쳤던 점은, 이동한 자리가 이미 지나간 자리 일 수도 있다는 것이다. 그래서 현재 자리에서 했던 if문을 이동한 자리에도 추가하였다.

수정한 코드는 다음과 같다.

if(map[x][y] == (char) 45 || map[x][y] == (char) 43 )
		map[x][y] = (char) 43;
else map[x][y] = (char) 124;

x = x-1;
if(map[x][y] == (char) 45 || map[x][y] == (char) 43 ) 
		map[x][y] = (char) 43;
else map[x][y] = (char) 124;

정답코드 (JAVA) - 정리 전.ver



import java.util.*;
import java.io.*;

public class Main {
	static int N;
	static String [] strs;
	static char [][] map;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		strs = br.readLine().split("");
		int count = strs.length;
		int x = N-1;
		int y = 0;
		map = new char [N][N];
		
		for(int i=0;i<N;i++) {
			Arrays.fill(map[i], (char)46); // 모든 곳을 . 으로 채우기 
		}

		int dist = 0;
		
		for(int i=0;i<count;i++) {
			
			if(strs[i].equals("U")&& x+1 <N) { //명령어가 U이면서 위로 칸이 막혀있지 않다면 
				if(map[x][y] == (char) 45 || map[x][y] == (char) 43) //이동전 방향이 동일하지 않다면
					map[x][y] = (char) 43;
				else map[x][y] = (char) 124;
				x= x+1;
				if(map[x][y] == (char) 45 || map[x][y] == (char) 43 )
					map[x][y] = (char) 43;
				else map[x][y] = (char) 124;
				
			}
				
			else if(strs[i].equals("D")&& x-1 >=0) {//명령어가 D이면서 아래로 칸이 막혀있지 않다면 
				if(map[x][y] == (char) 45 || map[x][y] == (char) 43 )
					map[x][y] = (char) 43;
				else map[x][y] = (char) 124;

				x = x-1;
				if(map[x][y] == (char) 45 || map[x][y] == (char) 43 ) 
					map[x][y] = (char) 43;
				else map[x][y] = (char) 124;
				
			}
				
			else if(strs[i].equals("R") && y+1 <N) {//명령어가 R이면서 오른쪽 칸이 막혀있지 않다면 
				if(map[x][y] == (char) 124 || map[x][y] == (char) 43)
					map[x][y] = (char) 43;
				else map[x][y] = (char) 45;
				
				y=y+1;
				if(map[x][y] == (char) 124 || map[x][y] == (char) 43)
					map[x][y] = (char) 43;
				else map[x][y] = (char) 45;
				
			}
			else if(strs[i].equals("L") && y-1 >=0) {//명령어가 L이면서 왼쪽 칸이 막혀있지 않다면 
				if(map[x][y] == (char) 124 || map[x][y] == (char) 43)
					map[x][y] = (char) 43;
				else map[x][y] = (char) 45;
				
				y=y-1;
				if(map[x][y] == (char) 124 || map[x][y] == (char) 43)
					map[x][y] = (char) 43;
				else map[x][y] = (char) 45;
				
				
			}

	
				
		}
		
		for(int k=N-1;k>=0;k--) {
			for(int j = 0; j<N;j++) {
				System.out.print(map[k][j]);
				
			}
			System.out.println();
		}

		
	}

}

이렇게 코드를 쓰니깐 안깔끔해보이고 중복되는 내용이 많았다. 그래서 나름대로 겹치는 내용을 함수로 빼보자! 하고 고친 코드가 아래와 같다.

정답코드 (JAVA) - 간결.ver

package coding_test;

import java.util.*;
import java.io.*;

public class B_1730_판화 {
	static int N;
	static String [] strs;
	static char [][] map;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		strs = br.readLine().split("");
		int count = strs.length;
		int x = N-1;
		int y = 0;
		map = new char [N][N];
		
		for(int i=0;i<N;i++) {
			Arrays.fill(map[i], (char)46); // 모든 곳을 . 으로 채우기 
		}

		int dist = 0;
		
		for(int i=0;i<count;i++) {
			
			if(strs[i].equals("U")&& x+1 <N) { //명령어가 U이면서 위로 칸이 막혀있지 않다면 
				checkUpDown(x,y);
				x= x+1;
				checkUpDown(x,y);
				
			}
				
			else if(strs[i].equals("D")&& x-1 >=0) {
				checkUpDown(x,y);

				x = x-1;
				checkUpDown(x,y);
				
			}
				
			else if(strs[i].equals("R") && y+1 <N) {
				checkLeftRight(x,y);
				
				y=y+1;
				checkLeftRight(x,y);
				
			}
			else if(strs[i].equals("L") && y-1 >=0) {
				checkLeftRight(x,y);
				
				y=y-1;
				checkLeftRight(x,y);
				
				
			}

	
				
		}
		
		for(int k=N-1;k>=0;k--) {
			for(int j = 0; j<N;j++) {
				System.out.print(map[k][j]);
				
			}
			System.out.println();
		}

		
	}
	static void checkUpDown(int x, int y) {
		if(map[x][y] == (char) 45 || map[x][y] == (char) 43) //이동전 방향이 - 였다면 +로 변경
			map[x][y] = (char) 43;
		else map[x][y] = (char) 124;
	}
	static void checkLeftRight(int x, int y) {
		if(map[x][y] == (char) 124 || map[x][y] == (char) 43)
			map[x][y] = (char) 43;
		else map[x][y] = (char) 45;
	}

}

if문으로 작성했던 map에 표시하는 코드를 위아래 / 좌우 함수로 나눠서 정리를 해두니, 중복되었던 코드 4개를 1개씩 2개로 정리할 수 있었다.

이 문제를 풀고 배운 점

  • 문제를 파악하기 위해, 각 예시별로 어떤게 변해야 하는 지를 먼저 파악하자 !
    • 이 문제를 풀고 가장 헤맸던 점은 이차원배열에서 시작점의 좌표가 어딘지 였다.
    • 문제를 읽고 이동하는 방향을 파악하고 이에 따라 어떤 변수가 변해야하는지를 먼저 알아야하는데, 나는 이걸 항상 놓친다.
  • 조건을 나눴을 때, 겹치는 내용이 많다면 하나의 함수로 표현하자.
profile
github : https://github.com/oU-Ua

0개의 댓글

관련 채용 정보