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
}
'Level-Up > 알고리즘' 카테고리의 다른 글
[백준] 17471. 게리맨더링 - 골드4 (0) | 2021.12.11 |
---|---|
[백준] 15683. 감시 - 골드5 (0) | 2021.12.07 |
[백준] 15684. 사다리 조작 - 골드4 (0) | 2021.10.12 |
[백준] 15686. 치킨배달 - 골드5 (0) | 2021.10.12 |
[백준] 2667. 단지번호붙이기 - 실버1 (0) | 2021.10.08 |