https://www.acmicpc.net/problem/20436
[문제]
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 |