
문제 한 줄 요약
N종류 동전의 최소 개수로 K를 만들어라. (동전의 개수가 무한대이므로 만들 수 없는 경우는 존재하지 않는다.)
내가 생각한 조건
최소 개수라 했으므로 입력받은 N을 오름차순으로 정렬한 후, 가장 많은 값부터 넣어가면서 비교하면 될 것 같았다.
(오름차순이라 정의되어 있으므로 다시 정렬할 필요는 없음.)
가장 많은 값부터 임의로 넣어가며 작업하면 될 것이라 생각했기 때문에 해당 상황에서 가장 적합한 값을 찾는 그리디 알고리즘이 적합할 것이라 생각했다.
작성한 코드
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 | #include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ int n, k; vector<int> v; int ans = 0; cin >> n >> k; for(int i = 0; i < n; i++) { int num; cin >> num; v.push_back(num); } int v_size = v.size()-1; int sub_cal = 0; for(int i = v_size; i >=0; i--) { if(v[i] > k) continue; else if(v[i] == k) { ans += 1; break; } else if(v[i] < k) { while(sub_cal < k){ sub_cal = sub_cal + v[i]; ans += 1; } if(sub_cal == k) break; sub_cal -= v[i]; ans -= 1; continue; } } cout << ans << '\n'; } | cs |
코드 작성 후 피드백
이 블로그 게시글을 참고했다.
나는 직관적으로 값을 계속 빼주는 값으로 계산했다.
그러나 예시를 들어 생각해 보았을 때, 2200원에서 1000원짜리는 2개를 쓰고 200원이 남는다.
이 말은 값을 나눠서 횟수를 구한 후, k는 %연산자를 사용해 갱신해주면 된다는 뜻이다.
이를 바탕으로 for문을 정리해보면 다음과 같다.
int suc_cal = 0;
for (i = n-1; i >= 0; i--)
{
sub_cal += k / v[i];
k %= v[i];
}
그리고 작성 코드를 보면 else if문에서 계산을 할 때 N과 K의 대소를 비교해서 if문을 작성하고, while문에서 무조건 N값을 더해주며 계산했기 때문에 while문을 빠져나올 경우 추가로 처리해야 하는 연산이 존재해서 비효율적이었다. (그리고 이후 K와 같을 때 조건문을 반드시 넣어서 조건을 따져줬기 때문에 비효율적)
참고 코드를 이용하면 k값이 실시간으로 바뀌어서 k=0이 되면 자동으로 해결이 된 것이기 때문에 굳이 복잡하게 식을 넣지 않아도 된다.
한줄평
너무 직관적으로만 코드를 작성한 것 같다. 좀 더 코드 내부에 있는 공식을 생각하는 습관을 가져야 할 것 같다.
### **Point** 그리디 알고리즘은 각 단계에서 가장 최선의 선택을 하는 방법이다. (그 방법을 가장 직관적으로 활용한 문제이다.) 특정 값 A를 주어진 값 B들을 사용해 조합하는 문제의 경우 **/, %연산자**를 떠올리자.
'이론 공부 내용 정리 > 알고리즘' 카테고리의 다른 글
c++ 시간 초과시 사용하는 코드에 대한 이해 (0) | 2022.07.30 |
---|---|
1. c++ 라이브러리<stack> (0) | 2022.07.27 |
백준 1107_리모컨 (0) | 2022.07.22 |
백준 1931_회의실 배정 (0) | 2022.07.17 |
0. c++라이브러리 <string> (0) | 2022.07.01 |