[백준] 17281. 야구



문제

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





풀이

제목을 뭐라고 쓸까 고민하다가 그냥 야구로 했다. 야구 규칙을 몰라서 무슨 소린지 이해하는데 한참 걸렸는데, 뭐가 됐든 그냥 조건을 그대로 구현하면 되는 시뮬레이션 문제이다. 문제 자체가 복잡한 건 아니라서 주석 설명으로도 충분하다고 생각한다. 참고로 1번 선수는 무조건 4번 타자라는 것만 기억하면 된다.




//
//  17281.cpp
//  BJ
//
//  Created by 신기열 on 11/11/2019.
//  Copyright © 2019 신기열. All rights reserved.
//

#include <stdio.h>
#include <iostream>

using namespace std;

int n;
int inning[50][10];
int order[10];
int visited[10];
int answer;


int calc(int order[10]){

    // turn은 이닝이 바뀌어도 순서는 유지해야 되므로 그걸 위한 변수이다. 따라서 이닝 밖에 선언해준다.
    int ans = 0; int turn = 1;
    
    // 모든 이닝을 돌면서
    for(int i = 0; i < n; i++){
        // 이닝이 바뀔 때마다 out, 야구장은 초기화 된다. 또한 out이 될 때 선수가 다 로테이션되기 전에 종료 되므로 turn을 다음 순서로 정해준다.
        int out = 0; int map[4] = { 0, }; int tturn = turn;
        
        // 3 아웃이 될 때까지 계속한다.
        while(out < 3){
            // 선수 9명에 대해 탐색한다.
            for(int j = tturn; j <= 9; j++){

                // 현재 이닝에 대해 현재 순서의 타자가 1 안타인 경우
                if(inning[i][order[j]] == 1){
                    // 3루에 사람이 있다면 홈으로 가고 1점 추가
                    if(map[3] == 1){
                        ans++; map[3] = 0;
                    }
                    // 2루는 3루로
                    if(map[2] == 1){
                        map[2] = 0; map[3] = 1;
                    }
                    // 1루는 2루로
                    if(map[1] == 1){
                        map[1] = 0; map[2] = 1;
                    }
                    // 타자는 1루로
                    map[1] = 1;
                }
                // 2 안타인 경우
                else if(inning[i][order[j]] == 2){
                    // 3루는 홈으로 가고 1점 추가
                    if(map[3] == 1){
                        ans++; map[3] = 0;
                    }
                    // 2루는 홈으로 가고 1점 추가
                    if(map[2] == 1){
                        ans++; map[2] = 0;
                    }
                    // 1루는 3루로
                    if(map[1] == 1){
                        map[1] = 0; map[3] = 1;
                    }
                    // 타자는 2루로
                    map[2] = 1;
                }
                // 3 안타일 경우
                else if(inning[i][order[j]] == 3){
                    // 3루는 홈으로 가고 1점 추기
                    if(map[3] == 1){
                        ans++; map[3] = 0;
                    }
                    // 2루는 홈으로 가고 1점 추가
                    if(map[2] == 1){
                        ans++ ;map[2] = 0;
                    }
                    // 1루는 홈으로 가고 1점 추가
                    if(map[1] == 1){
                        ans++; map[1] = 0;
                    }
                    //타자는 3루로
                    map[3] = 1;
                }
                // 홈런이면
                else if(inning[i][order[j]] == 4){
                    // 전부 홈으로 가고 1점 추가
                    if(map[3] == 1){
                        ans++; map[3] = 0;
                    }
                    if(map[2] == 1){
                        ans++ ;map[2] = 0;
                    }
                    if(map[1] == 1){
                        ans++; map[1] = 0;
                    }
                    ans++;
                }
                // 아웃이면 1아웃 추가
                else if(inning[i][order[j]] == 0){
                    out++;
                }
                // 이닝 시작 시에 다음 순서 타자 ~ 마지막 타자까지 돌았는데, 그 후로부턴 다시 1번부터 9번까지 돌아야하므로 tturn (다음 타자를 의미) = 1로 바꿔준다.
                // 그리고 turn은 이닝이 바뀌어도 유지되는 순서이므로 다음 타자가 바뀔 때마다 1씩 오르며, 다음 타자가 9를 넘어가버리면 다시 1번 타자로 바꿔준다.
                tturn = 1; turn++;
                if(turn > 9) turn = 1;
                // 3아웃이면 이닝 끝
                if(out >= 3) break;
            }
        }
    }

    return answer = max(answer, ans);
}

// 1번은 무조건 4번 타자로 가면 되게끔 순서를 정해주면 된다.
void DFS(int idx, int order[10], int visited[10]){
    
    if(idx > 9){
        answer = max(answer, calc(order)); return;
    }
    
    for(int i = 1; i <= 9; i++){
        if(i == 1){
            order[4] = i; visited[i] = 1;
        }
        // 다음 타순이 4번이면 건너 뛰어서 5번에 넣어주고, 아니면 그냥 다음 타순에 넣어주면 된다.
        else if(visited[i] == 0){
            order[idx] = i; visited[i] = 1;
            if(idx + 1 == 4) DFS(idx + 2, order, visited);
            else DFS(idx + 1, order, visited);
            order[idx] = 0; visited[i] = 0;
        }
    }
    
}



int main(){
    cin >> n;
    for(int i = 0; i < n; i++){
        for(int j = 1; j <= 9; j++){
            cin >> inning[i][j];
        }
    }
    DFS(1, order, visited);
    
    cout << answer;
    return 0;
}


댓글