View

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

 

17281번: ⚾

⚾는 9명으로 이루어진 두 팀이 공격과 수비를 번갈아 하는 게임이다. 하나의 이닝은 공격과 수비로 이루어져 있고, 총 N이닝 동안 게임을 진행해야 한다. 한 이닝에 3아웃이 발생하면 이닝이 종

www.acmicpc.net

 

문제 요약

총 N이닝 동안 게임을 진행. 한 이닝에 3아웃이 발생하면 이닝 종료. 공격과 수비 교체.

타자가 공을 쳐서 얻을 수 있는 결과는 안타, 2루타, 3루타, 홈런, 아웃 중 하나이다.

한 야구팀의 감독 아인타가 타순을 정하려고 한다. 아인타는 자신이 가장 좋아하는 선수인 1번 선수를 4번 타자로 미리 결정했다. 아인타는 각 선수가 어떤 결과를 얻는지 미리 알고 있다. 가장 많은 득점을 하는 타순을 찾고, 그 때의 득점을 구해 보자.

 

첫째 줄에 이닝 수가 주어지고, 둘째 줄부터 N개의 줄에는 각 선수가 각 이닝에서 얻는 결과가 주어진다. 

  • 안타: 1
  • 2루타: 2
  • 3루타: 3
  • 홈런: 4
  • 아웃: 0

 

문제 해결 아이디어

완전 탐색으로 풀었다. 나올 수 있는 모든 타순에 대해 경기를 진행하고, 가장 많은 득점을 출력했다.

이미 4번 타자는 정해져 있으므로 2번부터 9번 선수에 대해 타순을 정했다. 다 뽑히면 play()함수를 호출해서 시뮬레이션 했다.

시뮬레이션 하는 부분은 아웃카운트가 3개가 되기 전까지 while문을 돌렸다.

index 변수는 현재 몇 번 타자가 타석에 있는지 알려 준다.

base[] 배열은 해당하는 루상에 주자가 있는지 없는지 true, false로 확인시켜 주는 배열이다.

player 변수는 몇 번 선수인지 알려 주는 변수이다. (몇 번 선수인지와 몇 번 타자인지는 다름)

hit 변수는 타석 결과가 저장되는 변수이다.

 

여담이지만 야구를 좋아해서 재미있게 풀었다. ㅎㅎ

 

완성된 코드

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

public class Main {
	/*
	 * 564ms
	 */
	
	static int N, input[][], hitter[], result;
	static boolean[] visited;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		N = Integer.parseInt(br.readLine());
		input = new int[N][10]; // 9번타자까지 입력
		hitter = new int[10];
		visited = new boolean[10];
		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for (int j = 1; j <= 9; j++) {
				input[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		// 4번타자는 1번선수로 고정
		hitter[4] = 1;
		visited[1] = true;

		result = Integer.MIN_VALUE;

		pick(1);

		System.out.println(result);
	}

	private static void pick(int cnt) {
		if (cnt == 4) { // 4번타자 고정이라
			pick(cnt + 1);
			return;
		}

		if (cnt == 10) {
			play();
			return;
		}

		for (int i = 2; i <= 9; i++) {
			if (visited[i])
				continue;
			visited[i] = true;
			hitter[cnt] = i;
			pick(cnt + 1);
			visited[i] = false;
		}
	}

	// 현재 뽑힌 타순으로 게임을 해본다
	private static void play() {
		int index = 1; // 1번타자부터 시작
		int player, hit, outCnt = 0, score = 0;
		boolean[] base = new boolean[4]; // 루상의 주자 확인

		for (int i = 0; i < N; i++) {
			// 이닝 시작. 아웃카운트, 베이스 초기화
			outCnt = 0;  
			Arrays.fill(base, false);
			
			while (outCnt != 3) { // 아웃카운트가 세개 되기 전에 도는 반복문
				if (index == 10) { // 타자일순일 경우에 해당
					index = 1;
				}
				player = hitter[index]; // 1번타자부터 시작
				hit = input[i][player]; // 현재 플레이어의 타석 결과
				if (hit == 1) { // 안타
					for (int b = 3; b >= 1; b--) {
						if (base[b]) {
							if (b == 3) { // 3루에 사람이 있으면
								score++; // 득점
								base[b] = false;
								continue;
							}
							base[b] = false;
							base[b + 1] = true; // 1루씩 진루
						}
					}
					base[1] = true;
				} else if (hit == 2) { // 2루타
					for (int b = 3; b >= 1; b--) {
						if (base[b]) {
							if (b == 3 || b == 2) { // 3루 혹은 2루에 사람이 있으면
								score++; // 득점
								base[b] = false;
								continue;
							}
							base[b] = false;
							base[b + 2] = true; // 2루씩 진루
						}
					}
					base[2] = true;
				} else if (hit == 3) {
					for (int b = 3; b >= 1; b--) {
						if (base[b]) {
							score++; // 루상의 모든 주자 득점
							base[b] = false;
							continue;
						}
					}
					base[3] = true; // 타자는 3루로
				} else if (hit == 4) { // 홈런
					for (int b = 1; b <= 3; b++) {
						if (base[b]) { // 루상의 모든 주자 득점
							score++;
							base[b] = false;
						}
					}
					score++; // 홈런친 타자 점수까지
				} else if (hit == 0) {
					outCnt++;
				}
				index++;
			} // 아웃카운트 3개 될동안 도는 반복문

		}
		result = Math.max(score, result);
	} // end of play
}
Share Link
reply
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31