문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/72411
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
풀이과정
# 해석
파라미터로 orders (모든 주문) , course (코스를 구성하는 요리의 개수) 두가지가 주어지며,
orders에 담긴 단품메뉴들을 course에 적힌 개수만큼 조합해서 코스요리를 만드는 것이 목표입니다.
고려해야 할 점은
1. 코스요리로 만들 단품요리들은 2번이상 손님에게 주문된 메뉴여야 합니다.
2. 2번 이상 주문된 메뉴들이라도 전부 코스요리가 될 수 있는것은 아니며,
"코스를 구성하는 요리의 개수 별"로 가장 많이 주문된 메뉴들 만이 코스요리가 될 수 있습니다.
예를들어 3가지 요리로 구성된 코스요리 조합을 따져봤을 때
A B C
B D E
C B A
B E D
A B C
D F G
B D E
이런 결과가 나왔다면
A B C : 3번
B D E : 3번
D F G : 1번
주문되었으므로 "A B C", "B D E"가 코스요리가 되는 것입니다.
예제에서 봤듯이 A B C 와 C B A 는 같은 요리가 되며, 가장 많이 주문된 코스요리가 2개 이상이면 전부 코스요리가
될 수 있습니다.
# 풀이
1. 먼저 모든 주문(orders)에 대해 course 에 담긴 개수로 만드는게 가능한 조합의 경우의 수를 구해줘야 합니다.
주문한 단품메뉴의 개수가 course에 적힌 개수보다 크다면 조합을 구해주면 됩니다.
orders[i] C course[j]
* 다만 조건에 의해 A B C 와 C B A는 같은 요리가 되기 때문에 조합을 구하기 전에 먼저 정렬을 해주어야 합니다.
그 후 모든 경우의 수에 대해 map을 활용하여 어떤 코스요리가 몇번 주문되었는 지를 기록합니다.
// 주문으로 만들 수 있는 모든 조합을 찾는다.
for(string order:orders) {
sort(order.begin(), order.end());
for(int i=0; i<course.size(); i++) {
if(course[i] <= order.size()) comb(order,0,0,"",course[i]);
}
}
2. 다음으로 기록한 결과에 대해 두 번 이상 주문된 코스요리만 따로 저장해줍니다.
가장 많이 주문한 코스요리가 무엇인지 알아야 하기 때문에 주문 횟수에 대해 내림차순으로 정렬했습니다.
bool cmp(pair<int,string> a, pair<int,string> b) {
return a.first > b.first;
}
...
vector < pair <int, string> > sortV;
for(auto item:ordersMap) {
if(item.second >= 2) sortV.push_back({item.second, item.first});
}
// 주문 횟수로 내림차순 정렬
sort(sortV.begin(),sortV.end(),cmp);
3. 정렬한 코스요리들은 이제 주문횟수가 가장 많은 순서대로 정렬되어 있기 때문에
차례로 for문을 돌려서 정답을 구할 수 있습니다.
for(int i=0; i<course.size(); i++) {
int maxCnt = 0;
for(int j=0; j<sortV.size(); j++) {
string food = sortV[j].second;
// 크기가 같은 주문에 대해서만 체크
if(course[i] != food.size()) continue;
// 가장 많이 주문한 주문 저장
if(maxCnt == 0) {
answer.push_back(sortV[j].second);
maxCnt = sortV[j].first;
}
// 가장 많은 주문횟수가 또 있다면 저장
else if(maxCnt == sortV[j].first) answer.push_back(sortV[j].second);
// 그 이후는 고려하지 않음
else break;
}
}
sort(answer.begin(),answer.end());
전체 코드
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
bool check[10];
map < string, int > ordersMap;
// 조합
void comb(string s, int idx, int cnt, string result, int size) {
if(cnt == size) {
ordersMap[result]++;
return;
}
for(int i=idx; i<s.size(); i++) {
if(check[i] == 0) {
check[i] = 1;
result += s[i];
comb(s,i+1,cnt+1,result,size);
result.pop_back();
check[i] = 0;
}
}
}
bool cmp(pair<int,string> a, pair<int,string> b) {
return a.first > b.first;
}
vector<string> solution(vector<string> orders, vector<int> course) {
vector<string> answer;
// 주문으로 만들 수 있는 모든 조합을 찾는다.
for(string order:orders) {
sort(order.begin(), order.end());
for(int i=0; i<course.size(); i++) {
if(course[i] <= order.size()) comb(order,0,0,"",course[i]);
}
}
vector < pair <int, string> > sortV;
for(auto item:ordersMap) {
if(item.second >= 2) sortV.push_back({item.second, item.first});
}
// 주문 횟수로 내림차순 정렬
sort(sortV.begin(),sortV.end(),cmp);
for(int i=0; i<course.size(); i++) {
int maxCnt = 0;
for(int j=0; j<sortV.size(); j++) {
string food = sortV[j].second;
// 크기가 같은 주문에 대해서만 체크
if(course[i] != food.size()) continue;
// 가장 많이 주문한 주문 저장
if(maxCnt == 0) {
answer.push_back(sortV[j].second);
maxCnt = sortV[j].first;
}
// 가장 많은 주문횟수가 또 있다면 저장
else if(maxCnt == sortV[j].first) answer.push_back(sortV[j].second);
// 그 이후는 고려하지 않음
else break;
}
}
sort(answer.begin(),answer.end());
return answer;
}'algorithm' 카테고리의 다른 글
| [프로그래머스] - "튜플" C++ / 구현 / map (0) | 2022.07.18 |
|---|---|
| [프로그래머스] - "괄호 변환" C++ / 재귀 / stack (0) | 2022.07.13 |
| [프로그래머스] - "신고 결과 받기" C++ / map (0) | 2022.07.11 |
| 백준 4375 - 1 (모듈러 연산) (0) | 2022.05.03 |
| 백준 4375 - 1 (모듈러 연산) (0) | 2021.10.06 |