백준

[백준_20436번] ZOAC 3

빙수빈수 2021. 8. 12. 14:29

https://www.acmicpc.net/problem/20436

 

20436번: ZOAC 3

첫 번째 줄에는 두 알파벳 소문자 sL, sR이 주어진다. sL, sR은 각각 왼손 검지손가락, 오른손 검지손가락의 처음 위치이다. 그 다음 줄에는 알파벳 소문자로 구성된 문자열이 주어진다. 문자열의

www.acmicpc.net

[문제]

2020년 12월, 세 번째로 개최된 ZOAC의 오프닝을 맡은 성우는 누구보다 빠르게 ZOAC를 알리려 한다. 하지만 안타깝게도 성우는 독수리타법이다!

  • 독수리 타법이란 양 손의 검지손가락만을 이용해 타자를 치는 타법이다.
  • 성우는 한글 자음 쪽 자판은 왼손 검지손가락으로 입력하고, 한글 모음 쪽 자판은 오른손 검지손가락으로 입력한다.
  • a의 좌표가 (x1, y1)이고, b의 좌표가 (x2, y2)일 때, a에 위치한 성우의 손가락이 b로 이동하는 데에는 a와 b의 택시 거리 |x1-x2|+|y1-y2| 만큼의 시간이 걸린다.
  • 각 키를 누르는 데에는 1의 시간이 걸린다.
  • 성우는 두 손을 동시에 움직일 수 없다.
  • 성우가 사용하는 키보드는 쿼티식 키보드이며, 아래 그림처럼 생겼다.

 

바쁜 성우를 위하여 해당 문자열을 출력하는 데 걸리는 시간의 최솟값을 구해보자.

 

[입력 조건]

 첫 번째 줄에는 두 알파벳 소문자 sL, sR이 주어진다. sL, sR은 각각 왼손 검지손가락, 오른손 검지손가락의 처음 위치이다. 그 다음 줄에는 알파벳 소문자로 구성된 문자열이 주어진다. 문자열의 길이는 최대 100자이다. 빈 문자열은 주어지지 않는다.

 

[코드]

import java.util.Scanner;

public class BaekJoon_20436 {
	// 키보드의 상태가 저장되어 있는 배열, 이때 자판이 없는 곳은 X 저장
	static Character[][] keyboard= {{'q','w','e','r','t','y','u','i','o','p'}
					,{'a','s','d','f','g','h','j','k','l','X'}
					,{'z','x','c','v','b','n','m','X','X','X'}};
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		char sL=sc.next().charAt(0); // 왼손 검지손가락의 초기 위치
		char sR=sc.next().charAt(0); // 오른손 검지손가락의 초기 위치
		String str=sc.next(); 
		int time=0; // 총 걸리는 시간
		
		// 입력받은 문자열 탐색
		for(int i=0;i<str.length();i++) {
			char ch=str.charAt(i);
			
			// 모음인 경우 오른손 검지손가락 사용
			if(ch=='y'||ch=='u'||ch=='i'||ch=='o'||ch=='p'
			||ch=='h'||ch=='j'||ch=='k'||ch=='l'
			||ch=='b'||ch=='n'||ch=='m'){
				
				String hand=findIndex(sR); // 오른손이 위치한 알파벳의 인덱스 구하기
				String move=findIndex(ch); // 이동해야하는 알파벳의 인덱스 구하기
				
				// findIndex는 문자열로 반환되기 때문에 int 형식으로 변환
				int x1y2=Integer.parseInt(hand);
				int x2y2=Integer.parseInt(move);
				
				/*
				 * findIndex로 반환된 값이 "03"이라면 int형 03으로 바꾼 후
				 * 거리를 계산하기 위해 행의 값을 10으로 나눈 몫으로 구하고,
				 * 열의 값을 10으로 나눈 나머지의 값으로 구해 매개변수로 전달한다.
				 * 
				 * 두 좌표를 사용하여 이동 시간을 구해 time 값에 누적시킨다.
				 */
				time+=distacnce(x1y2/10,x1y2%10,x2y2/10,x2y2%10);
				
				sR=ch; // 오른손 위치 갱신
			}
			
			// 자음인 경우 왼손 검지손가락 사용
			else {
				String hand=findIndex(sL);
				String move=findIndex(ch);
				
				int x1y2=Integer.parseInt(hand);
				int x2y2=Integer.parseInt(move);
				
				time+=distacnce(x1y2/10,x1y2%10,x2y2/10,x2y2%10);
				
				sL=ch; // 왼손 위치 갱신
			}
			
			time+=1; // 자판을 누르는 1초 count
		}
		
		System.out.println(time);
	}
	
	/*
	 * 문자 c가 키보드상 어느 위치에 있는지 반환하는 함수
	 * 문자열 첫 번째에 행, 두 번째에 열이 저장되어 있는 형태로 반환
	 * 
	 * 예를들어 "03"은 키보드 0행의 3열에 있다는 의미
	 */
	public static String findIndex(char c) {
		String result=""; 
		for(int i=0;i<3;i++) {
			for(int j=0;j<10;j++) {
				if(keyboard[i][j]==c) {
					result+=i;
					result+=j;
				}	
			}
		}
		return result;
	}
	
	// 이동 시간 구하는 함수
	public static int distacnce(int x1, int y1, int x2, int y2) {
		return Math.abs(x1-x2)+Math.abs(y1-y2);
	}
}

 

[고찰]

 이번 문제는 풀면서도 이것보다 효율적으로 풀 수 있는 방법이 있을텐데 라는 생각을 가졌던것 같다. 그래도 혼자 힘으로 해결해보자 다짐했기 때문에 풀고난 뒤 시간초과 없이 정답처리를 받아 기뻤다. 이후 다른 사람의 코드를 참고해보자 싶어 검색해봤지만 모두 파이썬 코드라 자바에서는 지원하지 않는 함수들이 많아 참고할 수 없었다. 이후 실력이 더 는다면 위의 코드를 좀 더 간결하게 구성해보고 싶다.

'백준' 카테고리의 다른 글

[백준_18312번] 시각  (0) 2021.08.12
[백준_19532번] 수학은 비대면강의입니다  (0) 2021.08.12
[백준_2417번] 정수 제곱근  (1) 2021.08.12
[백준_1343번] 폴리오미노  (0) 2021.08.11
[백준_14916번] 거스름돈  (0) 2021.08.11