Algorithm/Programmers
[Programmers] 양궁 대회 (Java)
Jyuni
2024. 2. 19. 17:08
문제 출처 : https://school.programmers.co.kr/learn/courses/30/lessons/92342
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 풀이
라이언이 최대 점수차로 어피치를 이길 수 있는 과녁을 구한다.
과녁이 10개밖에 없기 때문에 가장 먼저 든 생각은 10번 반복문을 돌면서 점수를 먹는 경우, 안먹는 경우가 떠올랐다. 예제 1번을 예시로 들면 [2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0] 0번 Index의 10점을 얻으려면 3개의 화살이 필요하므로 cnt+3과 10점을 안먹는 경우 cnt를 그대로 넘기면서 하나의 Index 당 dfs를 2번 돌리면서 진행하며 남는 화살은 전부 0점 과녁인 10번 Index에 추가한다.
화살을 모두 사용했거나 마지막 Index까지 간 경우 maxScore를 최대값으로 갱신하고 현재 score상태를 clone()함수를 통해 ans배열에 저장한 후에 ans배열이 전부 0이면 최대값이 갱신되지 않은 경우이므로 {-1}을 return하고 아니라면 ans배열을 return한다.
※ 고려해야 할점
- 최대 점수차가 여러 경우일 경우 가장 낮은 점수를 더 많이 맞힌 경우 return
최대 점수차가 같은 경우가 많을 수도 있기 때문에 시간 단축을 위해 0번 Index부터 시작하지 않고 끝 Index부터 시작하여 마지막으로 갱신된 값이 가장 낮은 점수를 많이 맞힌 경우가 되므로 따로 검사하지 않을 수 있었습니다. - 점수 구하기
과녁을 모두 사용했을 경우 라이언과 어피치의 점수를 모두 구하는 것보다 라이언의 점수만 구하고 마지막에 어피치 점수와 비교하는 방식으로 조건문을 줄일 수 있었습니다. 이 방식을 사용하기 위해선 dfs를 시작하기 전에 점수판 board[11] 배열을 만든 후 어피치가 점수를 얻은 과녁판은 *2를 해준다. 이러면 어피치의 점수를 다시 계산하지 않고 라이언의 점수를 board[] 배열을 기준으로 구하고 마지막에 비교만 해준다면 코드와 시간을 줄일 수 있었습니다. - 라이언이 우승할 방법이 없는 경우 {-1} return
위와 같이 점수를 구한 후 마지막에 라이언의 점수가 어피치의 점수보다 같거나 작다면 -1을 return하고 아니라면 ans배열을 return한다면 조건에 맞는 과녁을 구할 수 있습니다.
코드
import java.util.*;
class Solution {
public int[] solution(int n, int[] info) {
// init
int apeachScore = 0;
for(int i=0; i<11; i++) {
if(info[i] > 0) {
apeachScore += (10-i);
board[i] = (10-i) * 2;
} else {
board[i] = (10-i);
}
}
dfs(n, 10, 0, info);
if(maxScore > apeachScore){
return ans;
}
return new int[] {-1};
}
int[] ans = new int[11];
int[] score = new int[11];
int[] board = new int[11];
int maxScore = 0;
public void dfs(int n, int now, int cnt, int[] info) {
if(cnt == n || now == -1) {
int nowScore = getScore();
if(nowScore >= maxScore) {
maxScore = nowScore;
ans = score.clone();
ans[10] += (n-cnt);
}
return;
}
dfs(n, now - 1, cnt, info);
if(cnt + info[now] + 1 <= n) {
int ryanScore = info[now] + 1;
score[now] = ryanScore;
dfs(n, now - 1, cnt+ryanScore, info);
score[now] = 0;
}
}
public int getScore() {
int ryanScore = 0;
for(int i=10; i>=0; i--) {
if(score[i] > 0) {
ryanScore += board[i];
}
}
return ryanScore;
}
}