안녕하세요! 테크지니어22입니다.
오늘은 프로그래머스 알고리즘 - 양궁대회 를 풀어보도록 하겠습니다.
https://school.programmers.co.kr/learn/courses/30/lessons/92342
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
[문제 접근]
처음에 얼핏 생각하면 과녁 점수마다 0~10발 맞힐 수 있으니 10^11이니 완전탐색이 불가능하고 그리디 알고리즘으로 접근해야하는 거아닌가라고 생각을 했습니다. 그러나 모든 과녁점수의 맞힌 횟수의 합이 n이기 때문에 시간복잡도가 현저히 낮다는 사실을 알 수 있고, 정확성 테스트를 위하 시간제한이 10초이고, n = 10이하여서 완전탐색을 생각했습니다.
완전탐색을 하기 위해 이중for문을 이용하여 접근을 시도했는데 잘되지 않았습니다. 이때 재귀를 이용한 완전탐색이 떠올랐고, 이를 이용하여 풀었습니다.
[풀이 전략]
1. 재귀 함수를 만듭니다.
2. 재귀 함수를 이용하여 라이언의 모든 경우의 수를 col이라는 벡터에 저장합니다.
3. 라이언의 모든 경우의 수를 확인하면서 스코어차이가 가장 큰 경우를 answer에 저장합니다. (이때, 제약조건들을 걸어줘야합니다)
4. answer가 비어있으면 -1을 삽입합니다.
[코드]
#include <string>
#include <vector>
using namespace std;
int num ;
vector<int> tmp ;
vector<vector<int>> col ;
void dfs(int cnt,int val) {
if(cnt == 11) {
col.push_back(tmp);
return;}
for(int i = 0 ; i <= val ; i++){
if(val >= i) {
tmp.push_back(i);
dfs(cnt+1, val - i);
tmp.pop_back();
}
}
}
vector<int> solution(int n, vector<int> info) {
vector<int> answer;
int dif = 0 ;
num = n ;
dfs(0,n);
for(auto v : col) {
int score1 = 0 ;
int score2 = 0;
for(int i = 0 ; i < 11 ; i++){
if(info[i] < v[i]) {
score2 += 10-i;
} else {
if(info[i] == 0 && v[i] == 0) continue;
score1 += 10-i;
}
}
if(score1 < score2) {
if(dif < score2 - score1) {
dif = score2 - score1 ;
answer = v;
} else if(dif == score2 -score1) {
for(int i = 10 ; i>= 0; i--){
if(answer[i] < v[i]) {
answer = v ;
break;
} else if(answer[i] > v[i]) break;
}
}
}
}
if(answer.empty()) answer.push_back(-1);
return answer;
}
[배울 점]
- 완전탐색에서 재귀를 이용하는 풀이 생각해보기. -> 그래프가 아니어도 재귀를 이용한 dfs풀이가 있다는 사실 기억하기.
'알고리즘 > 프로그래머스' 카테고리의 다른 글
[프로그래머스/C++] 알고리즘 - 메뉴 리뉴얼 (0) | 2024.05.25 |
---|---|
[프로그래머스/C++] 알고리즘 - 주차 요금 계산 (0) | 2024.05.23 |
[프로그래머스/C++] 알고리즘 - 도넛과 막대 그래프 (0) | 2024.05.16 |
[프로그래머스/C++] 알고리즘 - 주사위 고르기 (0) | 2024.05.12 |
[프로그래머스/C++] 알고리즘 - 두 큐 합 같게 만들기 (0) | 2024.05.12 |