[백준] 17281_야구공 (Java)

강민수·2023년 8월 20일

Algorithm-BACKJOON

목록 보기
48/55
post-thumbnail

✨ 문제


백준 17281 야구공

🎈 접근 방식


  1. 9명의 타선 정보를 먼저 정해야 하기 때문에 이 부분은 순열을 통해 해결해보자.
  2. 타선 정보가 정해졌다면 4번타자가 1번 선수일때의 경우에만 점수를 계산하도록 한다.
  3. 점수 계산은 1~3루까지 주자가 있는지 확인하면서 타자가 친 경우에 따라 점수를 올려주거나 주자를 이동시키고, 아웃이면 카운트를 세어주면서 3과 같아지면 이닝을 종료한다.
  4. 매 게임마다 점수 계산이 끝났으면 최댓값을 정답으로 출력한다.

고민이 많이 되었던 부분은 그냥 점수 계산을 할 때였는데 너무 어렵게 접근했던것 같다. 물론 코드가 좀 하드코딩으로 되어있다는 생각이 들긴 하지만 각 경우에 따라 세분화해서 접근하니깐 점수 계산은 성공했다!

😫 실수한 점이나 놓친 점


점수 계산을 하고 난 후에 1번 타석부터 9번까지 전부 다 쳤는데 아웃카운트가 3이 아니라면 즉, 이닝이 끝나지 않았다면 다시 1번으로 돌려줘야 하는데 이 부분을 안했다..

그리고 타자가 친 정보를 가져오기 위해 player 이차원 배열에 저장했는데 값을 가져올 때 처음엔 players[i][j]로 접근했다가 또 답이 나오지 않았고, 생각해보니 j는 타석 번호를 의미하는거고 그 타석에 선 선수번호는 넘겨받은 lineUp[]에 있었기에 lineUp[j - 1]로 접근해서 가져오니 되었다!

그리고 나는 NP 코드로 짜서 점수를 계산했는데 순열 코드로 하신 분들이 더 많았어서 코드를 다시 고쳐보기도 해봐야겠다.

💻 풀이 코드

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

public class Main {
	static int n, ans; // 이닝 수
	static int[] tgt; // 9명의 타선 정보
	static int[] src; // np를 만들기 위해 사용 1~9번까지 넣어두고
	static int[][] players; // 9이닝에 대한 9명 선수들의 정보

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		players = new int[n + 1][10]; // 1이닝부터 9이닝까지 1번부터 9번선수 기록
		StringTokenizer st;
		src = new int[9];

		for (int i = 0; i < 9; i++) {
			src[i] = i + 1;
		}

		for (int i = 1; i <= n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 1; j <= 9; j++) {
				players[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		// 타석을 정해준 다음
		// np를 이용해서 타석을 정했다면 4번 타자가 1번인 경우에만 보내준다.
		while (true) {
			if (src[3] == 1) {
				cal(src);
			}

			if (!np()) {
				break;
			}
		}

		System.out.println(ans);
	}

	static boolean np() {
		// 3가지 기억할 것
		// 1. 앞에서 교환되어야 하는 인덱스 & 작업
		int i = src.length - 1;
		// 오름차순이었다가 꺽이는 부분이 생길때까지 반복
		while (i > 0 && src[i - 1] >= src[i]) {
			i--;
		}
		if (i == 0) {
			return false;
		}
		// 2. 뒤에서 교환되어야 하는 인덱스 & 작업
		int j = src.length - 1;
		while (j > i - 1 && src[i - 1] >= src[j]) {
			j--;
		}
		// 3. 교환 후 뒤쪽을 작은수로 정리
		int temp = src[i - 1];
		src[i - 1] = src[j];
		src[j] = temp;
		Arrays.sort(src, i, src.length);

		return true;
	}

	// 정해진 타석에 따라서 플레이어 정보에 따라 게임 실시하고 점수 계산
	static void cal(int[] p) {
		int score = 0;
		int start = 1;

		for (int i = 1; i <= n; i++) {
			int out = 0;
			boolean[] base = new boolean[4]; // 1~4루까지 사람이 있는지 확인해서 점수 계산을 해줄려고

			outer: while (true) {
				// 1번부터 9번타석까지 이닝이 종료될때까지 반복
				for (int j = start; j <= 9; j++) {
					int hit = players[i][p[j - 1]]; // i이닝당 j번째 타석 선수가 치는 정보

					switch (hit) {
					case 0: // 그냥 아웃
						out++;
						break;
					case 1: // 1루타
						// 3루부터 확인해서 주자가 있으면 점수 추가해주고 주자 없는걸로 처리해주고
						if (base[3]) {
							score++;
							base[3] = false;
						}
						if (base[2]) {
							base[2] = false;
							base[3] = true;
						}
						if (base[1]) {
							base[2] = true;
							base[1] = false;
						}
						base[1] = true;
						break;
					case 2: // 2루타
						if (base[3]) {
							score++;
							base[3] = false;
						}
						if (base[2]) {
							score++;
							base[2] = false;
						}
						if (base[1]) {
							base[3] = true;
							base[1] = false;
						}
						base[2] = true;
						break;
					case 3: // 3루타
						if (base[3]) {
							score++;
							base[3] = false;
						}
						if (base[2]) {
							score++;
							base[2] = false;
						}
						if (base[1]) {
							score++;
							base[1] = false;
						}
						base[3] = true;
						break;
					case 4: // 홈런
						if (base[3]) {
							score++;
							base[3] = false;
						}
						if (base[2]) {
							score++;
							base[2] = false;
						}
						if (base[1]) {
							score++;
							base[1] = false;
						}
						score++;
						break;
					}

					if (out == 3) {
						start = j + 1;
						if (start == 10) {
							start = 1;
						}
						break outer;
					}
				}
				
				start = 1;
			}
		}

		ans = Math.max(ans, score);
	}
}
profile
능동적으로 개발 지식을 찾아다니는 백엔드 개발자입니다 😊 작성된 글에 대한 질문들 및 피드백은 언제나 환영입니다 :) 👌

0개의 댓글