문제
https://school.programmers.co.kr/learn/courses/30/lessons/258709
아이디어1
pair를 이용해서 pair<중복된 주사위 눈, 개수>로 변환하기
vector<vector<pair<int, int>>> dice_duple;
for (auto iter_d = dice.begin(); iter_d != dice.end(); ++iter_d)
{
vector<pair<int, int>> duple;
auto iter_n = iter_d->begin();
duple.emplace_back(pair<int, int>(*iter_n, 1));
iter_n++;
for (; iter_n != iter_d->end(); ++iter_n)
{
if (*iter_n == duple.back().first)
duple.back().second++;
else
duple.emplace_back(pair<int, int>(*iter_n, 1));
}
dice_duple.emplace_back(duple);
}
아이디어2-1
combination을 구현해서 가능한 주사위 조합 구하기
- [0 1 2] 과 [0 2 1] 같은 중복은 필요없기 때문에 permutation을 이용해서 없애도록 하자
1100이란 비트마스크와 prev_permutation를 이용하면
1100 / 1010 / 1001 / 0110 / 0101 / 0011
이 때, 1을 A의 주사위, 0을 B의 주사위라고 생각하면 됨
아이디어2-2
A의 승은 B의 패, B의 승은 A의 패
- 즉, combination의 절반은 필요가 없다
- 방법은 A는 항상 1번 주사위를 가지고 있다고 가정
- 절반의 경우의 수를 줄일 수 있음
- #1, #2를 구하면 #3, #4의 경우를 구할 필요가 없다
void combination(int N, int K, const vector<vector<pair<int, int>>>& dice, int& max, vector<int>& answer)
{
vector<bool> bitmask(K - 1, true);
bitmask.resize(N - 1, false);
do {
vector<int> numbers_A = { 0 };
vector<int> numbers_B;
for (int i = 0; i < N - 1; ++i)
{
if (bitmask[i] == true)
numbers_A.emplace_back(i + 1);
else
numbers_B.emplace_back(i + 1);
}
calculate(numbers_A, numbers_B, dice, max, answer);
} while (prev_permutation(bitmask.begin(), bitmask.end()));
}
아이디어3
unordered_map을 이용해서 <key : 합, value : 개수>로 저장
// key : 합, value : 수
unordered_map<int, int> sum_A;
unordered_map<int, int> sum_B;
// 첫 주사위 6개 넣어 초기화
auto iter_A = numbers_A.begin();
for (auto iter = dice[*iter_A].begin(); iter != dice[*iter_A].end(); ++iter)
{
sum_A.emplace((*iter).first, (*iter).second);
}
iter_A++;
// 다음 주사위들 합하기
for (; iter_A != numbers_A.end(); ++iter_A)
{
unordered_map<int, int> tempSum;
for (auto& ele : sum_A)
{
for (auto iter = dice[*iter_A].begin(); iter != dice[*iter_A].end(); ++iter)
{
// operator[]는 key가 없다면 생성, int의 경우 0초기화 보장
tempSum[ele.first + (*iter).first] += ele.second * (*iter).second;
}
}
swap(sum_A, tempSum);
}
auto iter_B = numbers_B.begin();
for (auto iter = dice[*iter_B].begin(); iter != dice[*iter_B].end(); ++iter)
{
sum_B.emplace((*iter).first, (*iter).second);
}
iter_B++;
for (; iter_B != numbers_B.end(); ++iter_B)
{
unordered_map<int, int> tempSum;
for (auto& ele : sum_B)
{
for (auto iter = dice[*iter_B].begin(); iter != dice[*iter_B].end(); ++iter)
{
tempSum[ele.first + (*iter).first] += ele.second * (*iter).second;
}
}
swap(sum_B, tempSum);
}
int win = 0;
int lose = 0;
for (auto A : sum_A)
{
for (auto B : sum_B)
{
if (A.first > B.first)
win += A.second * B.second;
else if (A.first < B.first)
lose += A.second * B.second;
}
}
if (max < win)
{
answer = numbers_A;
max = win;
}
if (max < lose)
{
answer = numbers_B;
max = lose;
}
다른 사람들이 올린 JS나 파이썬에 비하면 훨씬 빠르긴 한데 C++은 없어서 이게 언어적 차이로 빠른 건지 진짜 빠른 건지 모르겠다