오목

최민수·2023년 7월 31일
1

알고리즘

목록 보기
77/94
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;
		}
	}
}

S1

Java로 풀어본 알고리즘 문제였다.

우선 자바로 입력을 받는게 무척 익숙하지 않았는데, InputStream으로 BufferedReader 를 선언하고 readLine() 메서드를 통해서 입력을 한 줄씩 읽어오는 방법이었다.

처음에는 StringTokenizernextToken() 을 불러와서 값을 하나씩 받아왔는데 파싱에 문제가 있는지 한 줄의 모든 값을 가져오지 못했다.
그래서 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] // 이런 식으로 탐색
        // 따라서, 우선 순위는 자연스럽게 왼쪽, 그 다음은 위쪽이 된다.
    }
}

출처: https://www.acmicpc.net/problem/2615

profile
CS, 개발 공부기록 🌱

1개의 댓글

comment-user-thumbnail
2023년 7월 31일

유익한 글이었습니다.

답글 달기