https://www.acmicpc.net/problem/17281
접근 방식
(1). 4번 타자는 무조건 1번 선수
타석 순서 정하는 순열 함수를 수행하기 전에
4번타자 자리는 1번 선수로 고정시켜놓는다.
(2). 순열 함수로 타석 순서를 정한다.
이때 selected[i]=cnt가 들어가야한다.
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 | import java.util.Arrays; public class permutation { public static int[] array; public static int[] selectNum; public static boolean[] visited; public static int n; private static void permu(int cnt) { if (cnt==3) { System.out.println(Arrays.toString(selectNum)); return; } for(int i=1; i<=n; i++) { if(visited[i]) continue; visited[i]=true; selectNum[cnt]=i; permu(cnt+1); selectNum[cnt]=0; visited[i]=false; } } public static void main(String[] args) { // 순열 구현 array= new int[]{1,2,3,4,5,6,7}; n=array.length; selectNum= new int[3]; visited=new boolean[n+1]; permu(0); } } | cs |
(3). 타순 정했으니 게임 시작
1. 한 이닝에 3아웃 -> 종료 (이닝 교체 == 공격과 수비 교체)
2. 경기 시작 전, 타순을 정해야한다. (중간에 타순 변경 불가)
3. 9번 타자까지 공을 쳤는데 이닝이 끝나지 않으면 1번 타자가 다시 타석에 선다.
(타순은 이닝이 변경되어도 순서는 유지되어야함)
4. 1루 -> 2루 -> 3루 -> 홈 (1점+)
5. 안타(1루타), 2루타, 3루타, 홈런, 아웃
안타: *타자와 모든 주자*가 한 루씩 진루한다. -> 1
2루타: *타자와 모든 주자*가 두 루씩 진루한다. -> 2
3루타: *타자와 모든 주자*자가 세 루씩 진루한다. -> 3
홈런: *타자와 모든 주자*가 홈까지 진루한다. -> 4
아웃: 모든 주자는 진루하지 못하고, 공격 팀에 아웃이 하나 증가한다. -> 0
시행착오
- static 변수 초기화를 안해서 이번 문제도 역시나 헤맸다 ...
이럴거면 static 변수 쓰지 마라 ㅂㄷㅂㄷ
static 변수 초기화는 꼭 main 내에서 하는걸로 ^^
습관을 들이자
소스 코드
1. 방식1
순열 짤 때 원래 사용하던 방식대로 구현
selected[cnt]=i
4번 타석일 땐
permu(idx+1)을 호출하여
5번 타석부터 선택을 재개한다.
그리고 재귀 함수 permu(idx+1)의 작업이 끝났을때
4번 타석은 여전히 선수 선택을 하면 안되므로
return을 통해 함수를 종료시킨다.
즉, return을 해줌으로써 타석을 정해주는 구문인 for문을 거치지 않는다!
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | package day_0818; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Iterator; import java.util.StringTokenizer; public class n17281 { static int[] selected; // 순열로 뽑은 타석 순서 static boolean[] visited; // 방문 체크 static int P=9; // 플레이어 수 9명 static int maxCnt=0; // 최종출력값 static int[][] player; // 각 선수의 이닝 결과 저장배열 static int N; // 이닝수 public static void startGame() { int curCount=0; // 현재 스코어 int playerCnt=1; // 현재 타석에 서있는 선수의 번호 int outCount=0; // 아웃 카운트 // N 이닝을 반복한다. for (int i = 0; i < N; i++) { int[] state= {0,0,0}; // 현재 주자 상황 (1,2,3루) outCount=0; // 3아웃이 되기전까지 아래 과정을 반복한다. while (outCount<3) { int pResult = player[i][selected[playerCnt]]; // 타석에 서있는 선수의 점수 (해당 이닝의) if (pResult==0) outCount++; // 1. 아웃 else if(pResult==1) { // 2. 안타 -> 타자와 각 주자들 1칸씩 이동 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 3루 state[2]=1; state[1]=0; } if(state[0]>0) { // 1루 -> 2루 state[1]=1; state[0]=0; } // 타자 -> 1루 state[0]=1; } else if(pResult==2) { // 2. 2루타 -> 타자와 각 주자들 2칸씩 이동 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 홈 curCount++; state[1]=0; } if(state[0]>0) { // 1루 -> 3루 state[2]=1; state[0]=0; } // 타자 -> 2루 state[1]=1; } else if(pResult==3) { // 3. 3루타 -> 타자와 각 주자들 3칸씩 이동 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 홈 curCount++; state[1]=0; } if(state[0]>0) { // 1루 -> 홈 curCount++; state[0]=0; } // 타자 -> 3루 state[2]=1; } else if(pResult==4) { // 4. 홈런 -> 모든 주자 들어옴 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 홈 curCount++; state[1]=0; } if(state[0]>0) { // 1루 -> 홈 curCount++; state[0]=0; } // 타자 -> 홈 curCount++; } if (playerCnt==8) { playerCnt=9; }else { playerCnt=(playerCnt+1)%9; } } } maxCnt=Math.max(maxCnt, curCount); } public static void permu(int batIdx) { if(batIdx>P) { // 9번 선수까지 자리를 정해준 경우 // 2. 순열로 정한 타순으로 게임을 진행한다. startGame(); return; } if(batIdx==4) { permu(batIdx+1); // 4번타석 건너뛰고 5번타석부터 선택하기 return; // 4번 타석은 아래 for문 거치지 않고 함수 종료 } for (int i = 2; i <=P; i++) { if(visited[i]) continue; visited[i]=true; selected[batIdx]=i; permu(batIdx+1); visited[i]=false; } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); N=Integer.parseInt(br.readLine()); // 이닝 수 == 게임 수 // 1. 각 선수별로 이닝 결과 입력받기 player=new int[N][P+1]; for (int i = 0; i < N; i++) { StringTokenizer st = new StringTokenizer(br.readLine()); for (int j = 1; j <=P; j++) { player[i][j]=Integer.parseInt(st.nextToken()); } } visited=new boolean[P+1]; selected=new int[P+1]; // 1번 선수 -> 4번 타자 (고정) visited[1]=true; // 선수 체크 배열 (1번타자 - 방문) selected[4]=1; // 타석 방문 배열 (4번타자 - 1번선수) // 2.순열로 타석 순서 정하기 permu(1); // 1번 타자는 이미 선택되어있으므로 2번 타자부터 선택하면 System.out.println(maxCnt); } } | cs |
2. 방식2
selected[i]=cnt
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | package study; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class n17281 { static int[] selected; // 순열로 뽑은 타석 순서 static boolean[] visited; // 방문 체크 static int P=9; // 플레이어 수 9명 static int maxCnt=0; // 최종출력값 static int[][] player; // 각 선수의 이닝 결과 저장배열 static int N; // 이닝수 public static void startGame() { int curCount=0; // 현재 스코어 int playerCnt=0; // 현재 타석에 서있는 선수의 번호 int outCount=0; // 아웃 카운트 // N 이닝을 반복한다. for (int i = 0; i < N; i++) { int[] state= {0,0,0}; // 현재 주자 상황 (1,2,3루) outCount=0; // 3아웃이 되기전까지 아래 과정을 반복한다. while (outCount<3) { int pResult = player[i][selected[playerCnt]]; // 타석에 서있는 선수의 점수 (해당 이닝의) if (pResult==0) outCount++; // 1. 아웃 else if(pResult==1) { // 2. 안타 -> 타자와 각 주자들 1칸씩 이동 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 3루 state[2]=1; state[1]=0; } if(state[0]>0) { // 1루 -> 2루 state[1]=1; state[0]=0; } // 타자 -> 1루 state[0]=1; } else if(pResult==2) { // 2. 2루타 -> 타자와 각 주자들 2칸씩 이동 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 홈 curCount++; state[1]=0; } if(state[0]>0) { // 1루 -> 3루 state[2]=1; state[0]=0; } // 타자 -> 2루 state[1]=1; } else if(pResult==3) { // 3. 3루타 -> 타자와 각 주자들 3칸씩 이동 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 홈 curCount++; state[1]=0; } if(state[0]>0) { // 1루 -> 홈 curCount++; state[0]=0; } // 타자 -> 3루 state[2]=1; } else if(pResult==4) { // 4. 홈런 -> 모든 주자 들어옴 if(state[2]>0) { // 3루 -> 홈 curCount++; state[2]=0; } if(state[1]>0) { // 2루 -> 홈 curCount++; state[1]=0; } if(state[0]>0) { // 1루 -> 홈 curCount++; state[0]=0; } // 타자 -> 홈 curCount++; } playerCnt=(playerCnt+1)%9; } } maxCnt=Math.max(maxCnt, curCount); } public static void permu(int cnt) { if(cnt==P) { // 2. 순열로 정한 타순으로 게임을 진행한다. startGame(); return; } for (int i = 0; i < P; i++) { if(visited[i]) continue; selected[i]=cnt; // 아직 이해 못함 ^^, 일단 4번 타자자리에는 타자를 넣지 않는 작용을 하는 듯 visited[i]=true; permu(cnt+1); visited[i]=false; } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); N=Integer.parseInt(br.readLine()); // 이닝 수 == 게임 수 // 1. 각 선수별로 이닝 결과 입력받기 player=new int[N][P]; for (int i = 0; i < N; i++) { StringTokenizer st = new StringTokenizer(br.readLine()); for (int j = 0; j <P; j++) { player[i][j]=Integer.parseInt(st.nextToken()); } } visited=new boolean[P]; selected=new int[P]; // 1번 선수 -> 4번 타자 (고정) visited[3]=true; selected[3]=0; // 2.순열로 타석 순서 정하기 permu(1); System.out.println(maxCnt); } } | cs |
'여니의 취준 준비 > 코딩테스트 (Java)' 카테고리의 다른 글
[20207] 달력 in Java (0) | 2022.08.14 |
---|---|
[17471] 게리맨더링 in Java (0) | 2022.08.14 |
[4012] 요리사 in Java (0) | 2022.08.12 |
[*11286*] 절댓값 힙 in Java (0) | 2022.08.12 |
[15686] 치킨 배달 in Java (0) | 2022.08.12 |