본문 바로가기

코딩테스트/JAVA

[백준 JAVA] 17281번: ⚾

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

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	public static int N, ans = 0;
	public static int[][] result;
	public static int[] arr = new int[9], visited = new int[9];

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		// 1. 입력받기
		N = Integer.parseInt(br.readLine());
		result = new int[N][9];

		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < 9; j++) {
				result[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		// 2. 중복 순열을 통해 타순 정하기
		visited[0] = 1;
		dfs(0); // 27 * 8!

		System.out.println(ans);
	}

	private static void dfs(int depth) {
		if (depth == 9) {
			// 3. 이닝 반복하기
			int cur = ining();

			if (cur > ans) {
				ans = cur;
			}

			return;
		}

		for (int i = 1; i < 9; i++) {
			if (depth == 3) {
				dfs(depth + 1);
				break;
			}
			if (visited[i] == 0) {
				visited[i] = 1;
				arr[depth] = i;
				dfs(depth + 1);
				visited[i] = 0;
			}
		}
	}

	private static int ining() {
		int cnt = 0;
		int num = 0;
		int[] ru;
		for (int i = 0; i < N; i++) {
			int out = 0;
			ru = new int[3];
			while (out < 3) {
				int cur = arr[num]; // 현재 타석 타자 번호
				int ta = result[i][cur]; // 현재 이닝의 타자 결과

				switch (ta) {
				case 1: // 안타
					if(ru[2] == 1) // 3루에 타자가 있으면
						cnt++;
					for (int j = 1; j >= 0; j--) { // 뒤로 밀기
						ru[j+1] = ru[j];
					}
					ru[0] = 1;
					break;
				case 2: // 2루타
					for (int j = 1; j < 3; j++) {
						if (ru[j] == 1) { // 2,3루에 타자가 있으면
							ru[j] = 0; // 초기화
							cnt++; // 점수 증가
						}
					}
					if(ru[0] == 1) { // 1루에 타자가 있으면
						ru[0] = 0;
						ru[2] = 1; // 3루로 이동
					}
					ru[1] = 1;
					break;
				case 3: // 3루타
					for (int j = 0; j < 3; j++) {
						if (ru[j] == 1) { // 루에 타자가 있으면
							ru[j] = 0; // 초기화
							cnt++; // 점수 증가
						}
					}
					ru[2] = 1;
					break;
				case 4: // 홈런
					cnt++; // 자신은 들어옴
				 	for (int j = 0; j < 3; j++) {
						if (ru[j] == 1) { // 루에 타자가 있으면
							ru[j] = 0; // 초기화
							cnt++; // 점수 증가
						}
					}
					break;
				case 0:
					out++;
					break;
				}

				// 타순 돌기
				if (num == 8) {
					num = 0;
				} else {
					num++;
				}
			}
		}
		return cnt;
	}
}

 

## 풀이 사항
풀이 일자: 2024.10.18
풀이 시간: 60분
채점 결과: 정답
예상 문제 유형: DFS, 구현
시간: 580 ms
메모리: 80520kb

## 풀이 방법
1. 중복 순열을 이용하여 타순을 설정한다. 이때 4번째 타순인 경우엔 반드시 1번타자가 들어가야 하므로 바로 재귀해준뒤 for문을 빠져나간다.
2. 매 이닝마다 while문을 돌며 점수를 계산한다. 이닝이 교체될때 타순이 항상 0번부터 시작되지 않고 바로 전 이닝 타자부터 시작하므로 타자번호를 for문 밬에서 관리해준다.

'코딩테스트 > JAVA' 카테고리의 다른 글

[백준 JAVA] 1074번: Z  (0) 2024.10.23
[백준 JAVA] 4179번: 불!  (0) 2024.10.22
[백준 JAVA] 9370번: 미확인 도착지  (0) 2024.10.16
[백준 JAVA] 9935번: 문자열 폭발  (0) 2024.10.13
[백준 JAVA] 12100번: 2048 (Easy)  (0) 2024.10.11