대딩/프로그래머스풀이

[프로그래머스 lv2] 양궁대회 풀이

경아ㅏ 2022. 3. 24. 13:29

해설

중복 조합(순서를 고려하지 않고 중복을 허용하여 선택하는 방법)을 통해 0부터 10까지의 과녁 중 n발을 선택한다.

n번의 점수를 모두 고른 뒤 각 점수의 개수를 카운트하여 라이언 배열을 생성한다.

라이언과 어피치의 점수를 각각 합산했을 때 라이언이 이긴 경우, 점수 차의 최댓값을 갱신하며 라이언 벡터를 저장한다.

 

전체 코드

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <tuple>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <climits>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <string>
#include <sstream>
#include <iostream>

using namespace std;
using ii = pair<int, int>;
using iii = tuple<int, int, int>;

#define X first
#define Y second

int mx;
vector<int> tmp(15, 0);
vector<int> ret = {-1};


bool cmp(vector<int>& v1, vector<int>& v2) {
    
    for (int i=10; i>=0; i--) {
        if (v1[i] > v2[i]) return true;
        else return false;
    }
}

void combination(int k, int n, const vector<int>& info) {
    
    if (k == n) {
        
        //n개를 모두 골랐을 때 각 점수의 개수를 카운트하여 라이언 배열 생성
        vector<int> cnt(11, 0);
        for (int i=0; i<n; i++) cnt[10-tmp[i]]++;
        
        //라이언과 어피치의 점수 합산
        int L = 0, A = 0;
        for (int i=0; i<10; i++) {
            if (!cnt[i] && !info[i]) continue;
            if (cnt[i] > info[i]) L += (10-i);
            else A += (10-i);
        }
        
        //라이언이 진 경우
        if (L <= A) return; 

        //라이언이 이긴경우
        if (L-A < mx) return; //점수차가 최댓값보다 작은 경우
        if (L-A > mx) {ret = cnt; mx = L-A; return; } //점수차가 최댓값보다 큰 경우
        if (cmp(cnt, ret)) ret = cnt; //점수차가 최댓값과 같은 경우(배열 비교)
        return ;
    }
    
    int st = 0;
    if (k != 0) st = tmp[k-1];
    for (int i=st; i<=10; i++) {
        tmp[k] = i;
        combination(k+1, n, info);
    }
}

vector<int> solution(int n, vector<int> info) {
    
    //0부터 10까지의 과녁 중 n개 선택(중복 조합)
    combination(0, n, info);
    return ret;
}