import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
char[][] graph = new char[19][19];
// 입력
for (int i=0;i<19;i++) {
String line = bf.readLine();
for (int j = 0, index = 0; j < 19; index += 2, j++) {
graph[i][j] = line.charAt(index);
}
}
// 승자 체크
int[] dx = {0, 1, 1, -1};
int[] dy = {1, 0, 1, 1};
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (graph[j][i] == '1' || graph[j][i] == '2') {
for (int k = 0; k < 4; k++) {
int curX = j;
int curY = i;
int cnt = 1;
// + 방향 체크
while (true) {
curX += dx[k];
curY += dy[k];
if (checkRange(curX, curY)) {
if (graph[j][i] == graph[curX][curY]) {
cnt++;
} else {
break;
}
} else {
break;
}
}
curX = j;
curY = i;
// - 방향 체크
while (true) {
curX -= dx[k];
curY -= dy[k];
if (checkRange(curX, curY)) {
if (graph[j][i] == graph[curX][curY]) {
cnt++;
} else {
break;
}
} else {
break;
}
}
// 정답 체크
if (cnt == 5) {
System.out.println(graph[j][i]);
System.out.println((j + 1) + " " + (i + 1));
return;
}
}
}
}
}
// 비긴 경우
System.out.println(0);
}
private static boolean checkRange(int curX, int curY) {
if (0 <= curX && curX < 19 && 0 <= curY && curY < 19) {
return true;
} else {
return false;
}
}
}
Java로 풀어본 알고리즘 문제였다.
우선 자바로 입력을 받는게 무척 익숙하지 않았는데, InputStream
으로 BufferedReader
를 선언하고 readLine()
메서드를 통해서 입력을 한 줄씩 읽어오는 방법이었다.
처음에는 StringTokenizer
로 nextToken()
을 불러와서 값을 하나씩 받아왔는데 파싱에 문제가 있는지 한 줄의 모든 값을 가져오지 못했다.
그래서 index를 2개씩 늘려가며(공백 처리) char
형 배열에 옮겨 담았다.
**추가)
StringTokenizer nextToken()
에서의 에러를 어떻게 고칠지 생각해봤다.
st.countTokens()
로 단순하게 반복문을 돌리며 nextToken()으로 값을 한 개씩 가져오지 않고,
아래와 같이 st.hasMoreTokens()
메서드를 사용해 더이상 토큰이 없을 때까지 계속 읽어오는 방식을 사용하면 문제가 없다.
while (st.hasMoreTokens()) {
graph[i][c++] = Integer.parseInt(st.nextToken());
}
입력이 끝나고 메인 로직 또한 만만치 않았다.
우선 생각해봐야 할 것은 어떤 방식으로 탐색할 것인가
, 그리고 가장 왼쪽, 가장 위쪽
의 행렬 정보를 어떻게 받아올 것인가 였다.
먼저 bfs + 8방 탐색
방식을 떠올려 보았는데 사실 이렇게 할 필요는 없었다.
왜냐하면 19*19 그래프를 탐색할 때 이미 위쪽의 값들은 확인이 끝났기 때문이다.
따라서 아래, 오른쪽, 오른쪽 아래, 오른쪽 위
이렇게 4방향에 대해 탐색을 실행 + 반대쪽 방향으로 값이 이어져 있을 수도 있으니 체크 후 count==5
일 때를 체크하면 끝나는 로직이다.
이런 식으로 논리를 짜면 자연스럽게 가장 왼쪽, 가장 위쪽
을 따로 가져올 필요 없이, 탐색한 바로 그 위치를 가지고 오면 된다.
왜냐하면 그래프의 탐색 방식이 왼쪽 위에서 오른쪽 아래
까지 가는 방식이기 때문에 이미 지나쳐간 노드에서 정답이 나왔다면 이미 종료되었을 것이기 때문이다.
for (int i=0;i<19;i++){
for(int j=0;j<19;j++){
graph[j][i] // 이런 식으로 탐색
// 따라서, 우선 순위는 자연스럽게 왼쪽, 그 다음은 위쪽이 된다.
}
}
유익한 글이었습니다.