Category: 경우의 수

0

프로그래머스 - 양궁 대회 (Python)

https://programmers.co.kr/learn/courses/30/lessons/92342 프로그래머스 - 키패드누르기 Cpp 프로그래머스 - 키패드누르기 Python 유의 사항 화살을 맞춘 개수를 저장하고 정렬하는데 있어서 주의해야 한다. 정렬에 대한 가중치가 앞자리가 아닌 뒷자리 에 있으므로 값을 저장할 때 뒤집어서 저장한 후 내림 차순으로 정렬해 가장 큰 값을 가져와 해당 값을 뒤집으면 가장 낮은 점수를 많이 맞춘 순서대로 정렬된 값을 가져올 수 있다. cases = []maxDiff: int = 0results = []def getScore(index: int): return 10 - indexdef calScores(ryan: list, apeech: list) -> None: diff: int = 0 apeech_score: int = 0 ryan_score: int = 0 global maxDiff for i in range(11): if apeech[i] == 0 and ryan[i] == 0: continue if ryan[i] > apeech[i]: ryan_score += getScore(i) else: apeech_score += getScore(i) diff = ryan_score - apeech_score if diff <= 0: return if diff >= maxDiff: oneCase: str = ''.join(list(map(str, ryan[::-1]))) if(diff > maxDiff): results.clear() maxDiff = diff results.append(oneCase)def makeAllCase(start: int, choice: int, n: int, ryan: list) -> None: if(choice >= n): cases.append(ryan.copy()) return for i in range(start, 11): ryan[i] += 1 makeAllCase(i, choice+1, n, ryan) ryan[i] -= 1def solution(n, info): answer = [] ryan = [0] * 11 makeAllCase(0, 0, n, ryan) for case in cases: calScores(case, info) if len(results) > 0: results.sort(reverse=True) answer = list(map(int, results[0][::-1])) # print(answer) else: answer.append(-1) return answer

0

프로그래머스 - 양궁 대회 (Cpp)

https://programmers.co.kr/learn/courses/30/lessons/92342 프로그래머스 - 키패드누르기 Cpp 프로그래머스 - 키패드누르기 Python 유의 사항 화살을 맞춘 개수를 저장하고 정렬하는데 있어서 주의해야 한다. 정렬에 대한 가중치가 앞자리가 아닌 뒷자리 에 있으므로 값을 저장할 때 뒤집어서 저장한 후 내림 차순으로 정렬해 가장 큰 값을 가져와 해당 값을 뒤집으면 가장 낮은 점수를 많이 맞춘 순서대로 정렬된 값을 가져올 수 있다. #include <bits/stdc++.h>using namespace std;int max_diff = -1;vector<string> scores;int getValue(int idx) { return 10 - idx;}void calScore(vector<int> apeach, vector<int> ryan) { int diff = 0; int total_apeach = 0; int total_ryan = 0; for (int i = 0; i < 11; i++) { if (apeach[i] == 0 && ryan[i] == 0) { continue; } if (apeach[i] >= ryan[i]) { total_apeach += getValue(i); } else { total_ryan += getValue(i); } } if (total_ryan > total_apeach) { diff = total_ryan - total_apeach; } else { return; } string str; for (int i : ryan) { str += i + '0'; } reverse(str.begin(), str.end()); if (diff > max_diff) { max_diff = diff; scores.clear(); scores.push_back(str); } else if (diff == max_diff) { scores.push_back(str); }}void back_tracking(int depth, int idx, int n, vector<int>& apeach, vector<int>& ryan) { if (idx > 10) { return; } if (depth == n) { calScore(apeach, ryan); return; } ryan[idx] += 1; back_tracking(depth + 1, idx, n, apeach, ryan); ryan[idx] -= 1; back_tracking(depth, idx + 1, n, apeach, ryan);}vector<int> solution(int n, vector<int> info) { vector<int> answer; vector<int> ryan = vector<int>(11, 0); back_tracking(0, 0, n, info, ryan); if (max_diff == -1) { answer.push_back(-1); } else { sort(scores.begin(), scores.end(), greater<string>()); string str = scores[0]; reverse(str.begin(), str.end()); for (int i = 0; i < str.size(); i++) { answer.push_back(str[i] - '0'); } } return answer;}

0

프로그래머스 - 카드 짝 맞추기 (Cpp)

https://programmers.co.kr/learn/courses/30/lessons/72415 문제 풀이좌표를 이동할 때 고려해야 하는 상황이 2가지가 있다 첫 번째 상, 하, 좌, 우 한칸씩 이동하는 경우와 한번에 카드가 있는 곳이나 벽쪽으로 바로 이동하는 경우다.카드를 찾는 경우의 수를 만드는데 있어 고려해야 하는 사항이 2가지가 있다. 첫번째는 서로 다른 카드를 찾아가는 경우의 수와 같은 숫자를 찾는 순서를 정하는 경우의 수다.예를 들어 1 -> 2 -> 3 의 순서로 카드를 찾아간다고 하면 (1 -> 1 짝 찾는 순서) -> (2 -> 2 짝 찾는 순서) -> (3 -> 3 짝 찾는 순서) 를 고려해야 한다는 의미다. 경우의 수가 만들어지면 각 순서에 맞게 BFS를 이용해 최단거리를 구해주면 된다. 다만, 카드는 짝을 만다면 사라지므로 최단 거리를 찾을 때 board 에서 카드가 사라졌는지에 대한 여부도 고려하면서 이동해줘야 한다. 고려 사항 enter를 누르는 것도 count 1을 갖는다. 카드 뒤집는 모든 경우의 수를 계산해야 한다. 1, 2, 3 서로 다른 카드를 찾아가는 경우의 수를 찾는다. 각각의 순서를 고려 하므로 순열의 경우의 수를 갖는다. 1 -> 1, 2 -> 2, 3 -> 3 각각 짝을 만드는 방향이 단방향으로 정해진 것이 아니기 때문에 반대 방향에 대해서도 고려애 줘야 한다. 즉, 최대 경우의 수는 6! * 2 ^ 6 이된다. 이동할 때 카드가 사라졌는지 확인해야 한다. board 에서 각 카드의 위치 찾기int findCards(vector<vector<int>>& board) { int count = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int value = board[i][j]; if (value > 0) { cards[value].push_back({i, j}); count++; } } } return (count / 2);} 카드를 뒤집는 모든 경우의 수 찾기

0

프로그래머스 - 합승 택시 요금 (Cpp)

https://programmers.co.kr/learn/courses/30/lessons/72413 문제 풀이모든 간선의 weight가 음수가 아닌 값, 시작점 s에서 도착할 수 있는 거리의 최소 비용을 구하는 문제라 다익스트라를 이용해 문제를 해결할 수 있다. 시작점 s에서 시작해 x점까지 같이 이동하는 최소 비용 + x점에서 시작해 a점까지 이동하는 최소 비용 + x점에서 시작해 b점까지 이동하는 최소 비용 중에서 가장 값이 작은 값을 찾는 문제다.원리는 간단하지만 다익스트라에 대해 잘 알고 있어야 풀 수 있는 문제다. void dijkstra(int node) { for (int i = 1; i < 220; i++) { dist[node][i] = INF; } priority_queue<pair<int, int>> pq; pq.push(make_pair(0, node)); dist[node][node] = 0; while (!pq.empty()) { int nodeDist = -pq.top().first; int cntNode = pq.top().second; pq.pop(); if (dist[node][cntNode] != nodeDist) { continue; } for (pair<int, int> vertex : graph[cntNode]) { int nextWeight = nodeDist + vertex.second; int nextNode = vertex.first; if (nextWeight < dist[node][nextNode]) { dist[node][nextNode] = nextWeight; pq.push(make_pair(-nextWeight, nextNode)); } } }} 전체 소스 코드#include <bits/stdc++.h>using namespace std;const int INF = 987654321;long long dist[220][220];vector<vector<pair<int, int>>> graph;void dijkstra(int node) { for (int i = 1; i < 220; i++) { dist[node][i] = INF; } priority_queue<pair<int, int>> pq; pq.push(make_pair(0, node)); dist[node][node] = 0; while (!pq.empty()) { int nodeDist = -pq.top().first; int cntNode = pq.top().second; pq.pop(); if (dist[node][cntNode] != nodeDist) { continue; } for (pair<int, int> vertex : graph[cntNode]) { int nextWeight = nodeDist + vertex.second; int nextNode = vertex.first; if (nextWeight < dist[node][nextNode]) { dist[node][nextNode] = nextWeight; pq.push(make_pair(-nextWeight, nextNode)); } } }}int solution(int n, int s, int a, int b, vector<vector<int>> fares) { int answer = 0; graph = vector<vector<pair<int, int>>>(n + 1); for (vector<int> fare : fares) { int start = fare[0]; int end = fare[1]; int weight = fare[2]; graph[start].push_back(make_pair(end, weight)); graph[end].push_back(make_pair(start, weight)); } // dijkstra_start(s); for (int i = 1; i <= n; i++) { dijkstra(i); } long long minValue = INF; for (int i = 1; i <= n; i++) { if (minValue > dist[s][i] + dist[i][a] + dist[i][b]) { minValue = dist[s][i] + dist[i][a] + dist[i][b]; } } answer = minValue; return answer;}

0

프로그래머스 - 순위 검색 (JAVA)

https://programmers.co.kr/learn/courses/30/lessons/72412 문제 풀이이 문제는 그냥 문자열대 문자열로 부딪히게 되면 시간 초과가 날 수 밖에 없는 문제다. 선형적으로 풀면 info 배열의 최대 크기는 5만, query 배열의 최대 크기는 10만 이므로 최대 50억 연산을 하게 되므로 효율성 측면에서 문제가 생긴다.결국 이 문제는 어떤 방법을 이용해 검색할 것인가가 가장 큰 관건이 된다. 선형적인 탐색을 하는 방법이 아닌 O(logn)의 시간 복잡도를 갖는 자료구조 혹은 탐색 기법을 이용하는 방법으로 문제를 접근해야 한다. 동시에 만들 수 있는 문장의 경우의 수를 고려해줘야 한다. 복합적인 문제라 쉽지 않다. 처음에 각 문자열내 문자들을 파싱해서 map에다가 저장을 해야 하나?…. 그러면 탐색을 어떻게 해야하지?… 하면서 문제 접근을 못하다가 다른 분 풀이를 살짝 참고 했는데 문자열 자체를 map의 key값으로 넣는 것을 보고 힌트를 얻어 문제를 접근할 수 있었다. info 내 문자열을 정재해 띄어쓰기는 문장을 만들어준다. key로 정재된 문장을 value로는 같은 key를 갖는 문장에 대한 값들을 보관하기 위해 List형태로 넣어준다. info 내 문장들이 map으로 다 들어갔으면 Binary Search를 사용하기 위해 오름 차순으로 정렬 해준다. query 내 문자열을 정재해 준다. info에서 구분자는 띄어쓰기 였지만 query에서 구분자는 and와 띄어쓰기다. ‘-‘를 만나게 되면 만들 수 있는 문장의 모든 경우의 수를 만들어준다. 정재된 문자를 갖고 info에 값이 있는지 확인한다. 값이 있으면 List에서 query에서 요구하는 값 이상이 되는 사람 수를 찾는다.(Lower Bound) 쿼리가 여러개인 경우는 각각의 경우들을 모두 찾아서 더해준다. 찾은 결과를 answer에 넣어 반환한다. info 내 문자열을 정재하기public void infoToMap(String[] info) { for (int i = 0; i < info.length; i++) { String[] words = info[i].split(" "); StringBuilder sb = new StringBuilder(); int score = Integer.parseInt(words[words.length - 1]); for (int j = 0; j < words.length - 1; j++) { sb.append(words[j]); } String key = sb.toString(); infos.computeIfAbsent(key, k -> new ArrayList<>()).add(score); }} map 내 List값들을 오름차순으로 정렬하기infos.forEach((key, value) -> { value.sort(null);});

0

프로그래머스 - 메뉴 리뉴얼 (JAVA)

https://programmers.co.kr/learn/courses/30/lessons/72411 문제 풀이처음에 문자열 비교로 접근해 엄청 해멨다. 이 문제는 문자열 비교로 접근을 하는게 아니라 한 사람이 시킨 메뉴 코스를 이용해 만들 수 있는 경우의 수를 만들어 비교하는 문제다. 코스를 사전 순서로 저장할 수 있도록 주문을 정렬해준다. 한 손님이 주문한 단품 메뉴들로 만들 수 있는 모든 코스 조합을 만들어준다. 코스내 메뉴 개수에 따라 가장 많이 선택된 횟수를 저장해 놓는다. 코스를 선택할때 코스내 메뉴가 메뉴 개수에서 가장 많이 선택된 횟수와 같다면 넣어준다. 모든 코스를 만들어주는 함수public void findAllCourse(String order, String subOrder, int depth) { if (depth == order.length()) { if (subOrder.length() > 1) { if (map.containsKey(subOrder)) { int value = map.get(subOrder); map.put(subOrder, value + 1); } else { map.put(subOrder, 1); } } return; } findAllCourse(order, subOrder + order.charAt(depth), depth + 1); findAllCourse(order, subOrder, depth + 1);} 전체 소스import java.io.*;import java.util.*;class Solution { Map<String, Integer> map = new TreeMap<>(); public void findAllCourse(String order, String subOrder, int depth) { if (depth == order.length()) { if (subOrder.length() > 1) { if (map.containsKey(subOrder)) { int value = map.get(subOrder); map.put(subOrder, value + 1); } else { map.put(subOrder, 1); } } return; } findAllCourse(order, subOrder + order.charAt(depth), depth + 1); findAllCourse(order, subOrder, depth + 1); } public String[] solution(String[] orders, int[] course) { for (String order : orders) { // 문자열내 문자들을 사전 순서대로 정렬 char[] charArr = order.toCharArray(); Arrays.sort(charArr); String sortedOrder = new String(charArr); // 주문한 메뉴들로 만들 수 있는 모든 코스 조합을 만들어준다. findAllCourse(sortedOrder, "", 0); } int[] maxValues = new int[101]; ArrayList<String> result = new ArrayList<>(); map.forEach((key, value) -> maxValues[key.length()] = Math.max(maxValues[key.length()], value)); map.forEach((key, value) -> { if (value >= maxValues[key.length()] && value > 1) { for (int i = 0; i < course.length; i++) { if (course[i] == key.length()) { result.add(key); } } } }); String[] answer = new String[result.size()]; int index = 0; for (String s : result) { answer[index++] = s; } return answer; }}

0

프로그래머스 - 메뉴 리뉴얼 (Cpp)

https://programmers.co.kr/learn/courses/30/lessons/72411 문제 풀이처음에 문자열 비교로 접근해 엄청 해멨다. 이 문제는 문자열 비교로 접근을 하는게 아니라 한 사람이 시킨 메뉴 코스를 이용해 만들 수 있는 경우의 수를 만들어 비교하는 문제다. 코스를 사전 순서로 저장할 수 있도록 주문을 정렬해준다. 한 손님이 주문한 단품 메뉴들로 만들 수 있는 모든 코스 조합을 만들어준다. 코스내 메뉴 개수에 따라 가장 많이 선택된 횟수를 저장해 놓는다. 코스를 선택할때 코스내 메뉴가 메뉴 개수에서 가장 많이 선택된 횟수와 같다면 넣어준다. 모든 코스 조합을 만들어주는 함수void makeAllCourse(string subOrder, string order, int depth) { if (depth > order.size()) { return; } if (depth == order.size() && subOrder.size() > 1) { if (m.find(subOrder) == m.end()) { m[subOrder] = 1; } else { m[subOrder] += 1; } } // 현재 메뉴를 선택하고 다음 메뉴로 넘어간다. makeAllCourse(subOrder + order[depth], order, depth + 1); // 현재 메뉴를 선택하지 않고 다음 메뉴로 넘어간다. makeAllCourse(subOrder, order, depth + 1);} 전체 소스#include <bits/stdc++.h>using namespace std;map<string, int> m;int maxValues[100];void makeAllCourse(string subOrder, string order, int depth) { if (depth > order.size()) { return; } if (depth == order.size() && subOrder.size() > 1) { if (m.find(subOrder) == m.end()) { m[subOrder] = 1; } else { m[subOrder] += 1; } } makeAllCourse(subOrder + order[depth], order, depth + 1); makeAllCourse(subOrder, order, depth + 1);}vector<string> solution(vector<string> orders, vector<int> course) { vector<string> answer; for (int i = 0; i < orders.size(); i++) { sort(orders[i].begin(), orders[i].end()); makeAllCourse("", orders[i], 0); } for (auto iter = m.begin(); iter != m.end(); iter++) { int courseCount = iter->first.length(); maxValues[courseCount] = max(maxValues[courseCount], iter->second); } for (auto iter = m.begin(); iter != m.end(); iter++) { int courseCount = iter->first.length(); if (iter->second == maxValues[courseCount] && iter->second >= 2) { for (int i = 0; i < course.size(); i++) { if (courseCount == course[i]) { answer.push_back(iter->first); } } } } return answer;}