프로그래머스 코딩테스트 실전 대비 모의고사 3회
1번
주어진 대로 반복문을 써서 풀면 되는 문제.
int solution(int give, int take, int cur) { int answer = 0; while(cur >= give){ // 현재 가지고 있는 게 주는 것보다 많으면 줄 수 이씅ㅁ int ret = (cur / give) * take; // 돌려받는 것 answer += ret; cur = cur - ((cur / give) * give) + ret; // 현재 개수 = 현재 개수 - 준 것 + 돌려받은 것 } return answer; }
2번
뒤에서 4개가 주어진 조건을 만족한다면, 그것을 빼고 추가하면 되는 문제. list를 쓸까 vector를 쓸까 고민하다가 결국 더 빠른 vector를 선택했다. vector의 erase, remove의 차이에 대해 알아두자.
int solution(vector<int> ingredients) { int answer = 0; vector<int> cur; for(int i = 0, cidx = 0; i<ingredients.size(); i++){ cur.push_back(ingredients[i]); int csize = cur.size(); if(csize >= 4){ if(cur[csize-1] == 1 && cur[csize-2] == 3 && cur[csize-3] == 2 && cur[csize-4] == 1){ cur.erase(cur.begin() + csize - 4, cur.end()); answer++; } } } return answer; }
3번
'경계 지역'에 근무를 서는 최솟값을 알아내면 되는 문제. 문제 자체는 [1 <= (i % cycle_time) <= guard[2]]라는 규칙이 있어서 쉬운데, 모든 경계 지역에 대해 이 값을 알아내야 하면 시간초과가 날 것 같았는데, 생각보다 테스트 케이스가 빈약했던 문제.
bool cmp(vector<int>& a, vector<int>& b){ if(a[0] == b[0]){ if(a[1] == b[1]){ if(a[2] == b[2]){ return a[3] < b[3]; } return a[2] < b[2]; } return a[1] < b[1]; } return a[0] < b[0]; } int solution(int distance, vector<vector<int>> scope, vector<vector<int>> times) { vector<vector<int>> guards(scope.size()); // [i][0] : 경계 시작 지점, [i][1] : 경계 끝 지점 // [i][2] : 근무 시간, [i][3] : 휴식 시간 for(int i = 0; i<scope.size(); i++){ if(scope[i][0] > scope[i][1]){ guards[i].push_back(scope[i][1]); guards[i].push_back(scope[i][0]); } else{ guards[i].push_back(scope[i][0]); guards[i].push_back(scope[i][1]); } guards[i].push_back(times[i][0]); guards[i].push_back(times[i][1]); } sort(guards.begin(), guards.end(), cmp); int answer = distance; for(vector<int>& guard : guards){ int cycle_time = guard[2] + guard[3]; // 감시하는 구간에 근무시간이라면 break // 어떤 i가 근무 시간에 있는 건... // 1 <= (i % cycle_time) <= guard[2] // 이면 근무 시간이라는 것을 판별할 수 있음 for(int i = guard[0]; i<=guard[1]; i++){ int remainder = i%cycle_time; if(1 <= remainder && remainder <= guard[2]){ answer = min(answer, i); } } } return answer; }
4번
꽤나 재밌었던 문제. DFS의 특성을 이용해서 [현재 칸을 색칠하는 경우, 그렇지 않은 경우]에 대해 최소 색칠 횟수를 leaf에서부터 가지고 올라와야 한다.
만약 parent를 색칠했다면 child는 색칠해도 되고, 색칠하지 않아도 되므로 parent.first(색칠한 경우) += min(child를 색칠한 경우, child를 색칠하지 않은 경우)이고, parent를 색칠하지 않았다면 child는 색칠해야 하므로 parent.second(색칠하지 않은 경우) += child를 색칠한 경우로 문제를 풀면 된다.
typedef pair<int, int> pii; int N; vector<int> visited; vector<vector<int>> edges; // .first : cur을 색 칠한 경우 최소 색칠 횟수, .second : cur을 색칠하지 않은 경우 최소 색칠 횟수 pii dfs(int cur){ visited[cur] = true; pii result = {1, 0}; // .first : cur을 색칠한 경우 for(int adj : edges[cur]){ if(!visited[adj]){ pii child_result = dfs(adj); result.first += min(child_result.first, child_result.second); // cur을 색칠했다면 child는 색칠해도 되고, 안 해도 됨 result.second += child_result.first; // cur을 색칠하지 않았다면 child을 색칠되어 있어야 함 } } return result; // child가 없다면 {1, 0}을 리턴. } int solution(int n, vector<vector<int>> lighthouse) { N = n+1; visited.resize(N); fill(visited.begin(), visited.end(), false); edges.resize(N); for(vector<int>& vi : lighthouse){ edges[vi[0]].push_back(vi[1]); edges[vi[1]].push_back(vi[0]); } pii answer = dfs(1); return min(answer.first, answer.second); }
'PS > PS Log' 카테고리의 다른 글
22.08.17. 풀었던 문제들 (0) | 2022.08.20 |
---|---|
22.08.16. 풀었던 문제들 (0) | 2022.08.16 |
22.08.14. 풀었던 문제들 (0) | 2022.08.15 |
22.08.13. 풀었던 문제들 (0) | 2022.08.13 |
22.08.12. 풀었던 문제들 - Codeforces #805 Div. 3 4/7 (0) | 2022.08.13 |