코딩 공부/백준

[백준][C++] 17281 야구

김 정 환 2021. 2. 5. 16:17
반응형

 

 

 

알고리즘 종류

    - 구현

    - 브루트포스

 

 

 

사고 과정

    1. 순열조합으로 타자의 순서 정하기

    2. 각 조합에 따라 점수 구하기

        조건 1. 3 아웃이면 이닝 종료

        조건 2. 타순은 한 이닝이 끝나면, 다음 이닝에서 계속 이어짐

        조건 3. 안타면 모든 선수 1칸 이동, 2루타면 모든 선수 2칸 이동, ...

    3.  각 조합의 모든 이닝이 끝나면 다른 조합의 결과와 점수 비교하여 최고 점수 저장

 

 

 

구현(C++)

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
int n;
int answer = 0;
// 각 이닝에서 타자의 결과
int mat[51][10];
int isSelected[10];
// 타순(타자가 치는 순서) 
vector<int> seq;
 
void get_score(){
    
    int game = 1;
    // 선수의 순서는 이닝 전체에 적용됨으로 여기에 선언 
    int turn = 1;
    int score = 0;
    // 필드 상태. 홈:0, 1루:1. 2루:2, 3루:3, 점수:4 
    int state[5];
    
    vector<int> seq2 = seq;
    // 1번 타자를 4번 순서에 넣기 
    seq2.insert(seq2.begin()+31);
    
    while(true){
        // 이닝 횟수  
        if(game == n+1break;
        
        int out = 0;
        // 이닝마다 필드 상태 초기화  
        memset(state, 0sizeof(state));
        
        // 3아웃이면 이닝 종료 
        while(out != 3){
            
            // 순서에 해당하는 선수의 결과가 0이면(아웃)  
            if(mat[game][seq2[turn-1]] == 0){
                out++;
                turn++;
                if(turn == 10) turn = 1;
                continue;
            } else {
                // 아웃 아니면 필드에 나갈 준비  
                state[0= 1;
            }
            
            // 필드에 나가게 되면, 선수들을 밀어야 한다.  
            for(int i=3; i>=0; i--){
                // 밀려났을 때, 홈으로 들어가면 점수 +1 
                if(i + mat[game][seq2[turn-1]] >= 4){
                    if(state[i]){
                        state[4]++;
                        state[i] = 0;
                    }
                }
                // 밀렸을 때, 홈에 들어가지 못하면, 위치 옮기기  
                else if(i + mat[game][seq2[turn-1]] < 4){
                    if(state[i]){
                        state[i + mat[game][seq2[turn-1]]] = 1;
                        state[i] = 0;
                    }
                }
            }
            
            // 선수가 쳤으니 다음 순서  
            turn++;
            if(turn == 10) turn = 1;
        }
        
        // 3 아웃으로 1회 이닝이 끝나면 점수 저장하기  
        score += state[4];
        game++;
    }
    
    // 모든 이닝이 끝나고 다른 순서 조합과 비교하기  
    answer = max(answer, score);
    
}
 
void combination(int cnt){
    if(cnt == 9){
        // 조합에 의한 순서로 점수 구해보기  
        get_score();
        return;
    }
 
    // 1번 타자 제외하고 순서 정하기     
    for(int i=2; i<=9; i++){
        if(isSelected[i]) continue;
        isSelected[i] = 1;
        seq.push_back(i);
        combination(cnt+1);
        seq.pop_back();
        isSelected[i] = 0;
    }
}
 
 
void solution(){
    // 순열조합으로 타순 결정하기  
    combination(1);
    cout << answer << endl;
}
 
 
int main(void){
    cin >> n;
    
    for(int i=1; i<=n; i++){
        for(int j=1; j<=9; j++){
            cin >> mat[i][j];
        }
    }
    solution();
}
 
 
cs

 

 

 

시행착오

    - 각 이닝에서 선수의 순서가 바뀌는 줄 알고 걱정하느라 시간을 낭비했다. 안 바뀌는데...

    - 타자가 공을 치고 필드에 나갈 때 어떻게 선수들을 움직이고 점수를 옮길까 고민했다. 나눗셈으로 할까 queue를 쓸까 고민했다. 결국 배열을 각 필드를 나타내기로 했다. state[5]로 만들어서, [0]은 홈이고 [3]은 3루로 정했다. 그리고 [4]는 점수를 저장하기로 했다. 3루에서 홈으로 들어가면 1점이니 그것을 표현했다.

    - 그닥 어렵지 않았지만, 야구라는 소재를 사용해서 본인 혼자 어렵게 느꼈던 것 같다. 야구 경기를 본 경험도 없고 규칙도 거의 모르기 때문일 것이다. 

반응형

'코딩 공부 > 백준' 카테고리의 다른 글

[백준][C++] 12015 가장 증가하는 부분 수열 2  (0) 2021.02.06
[백준][C++] 1806 부분합  (0) 2021.02.06
[백준][C++] 1238 파티  (0) 2021.02.04
[백준][C++] 9935 문자열 폭발  (0) 2021.02.03
[백준][C++] 9251 LCS  (0) 2021.02.03