Coding Test/programmers

[프로그래머스] 양궁대회 c++

owls 2022. 9. 26. 13:30
728x90

문제 설명

카카오배 양궁대회 결승전에 라이언과 어피치가 대결한다.

어피치가 먼저 화살을 모두 쏜 후, 라이언이 화살을 모두 쐈을 때, 라이언이 큰 점수 차이로 이기는 방법을 구하는 문제이다. (방법이 여러개라면, 가장 낮은 점수를 더 많이 맞히 경우가 정답이다.)

 

점수 계산법

  -  k점을 여러 발 맞혀도 k점 보다 많은 점수를 가져가는 게 아니고 k점만 가져감.

     10점에 어피치가 3발, 라이언이 2발 쐈다면 어피치가 10점을 얻게 되고 라이언은 0점을 얻게된다.

     라이언이 점수를 획득하기 위해서는 어피치보다 +1개를 쏴야 점수도 얻고 불필요한 화살 소모를 줄일 수 있다.

     효율적으로 점수를 획득해야 한다.

    

     불필요한 화살 소모는 다음과 같다.

     1) K점 과녁에 a개 이하의 화살을 쏘는 경우

     2) K점 과녁에 a개 보다 훨씬 더 많은 화살을 쏘는 경우

 

 

제한 사항

  • 1 ≤ n ≤ 10
  • info의 길이 = 11
    • 0 ≤ info의 원소 ≤ n
    • info의 원소 총합 = n
    • info의 i번째 원소는 과녁의 10 - i 점을 맞힌 화살 개수입니다. ( i는 0~10 사이의 정수입니다.)
  • 라이언이 우승할 방법이 있는 경우, return 할 정수 배열의 길이는 11입니다.
    • 0 ≤ return할 정수 배열의 원소 ≤ n
    • return할 정수 배열의 원소 총합 = n (꼭 n발을 다 쏴야 합니다.)
    • return할 정수 배열의 i번째 원소는 과녁의 10 - i 점을 맞힌 화살 개수입니다. ( i는 0~10 사이의 정수입니다.)
    • 라이언이 가장 큰 점수 차이로 우승할 수 있는 방법이 여러 가지 일 경우, 가장 낮은 점수를 더 많이 맞힌 경우를 return 해주세요.
      • 가장 낮은 점수를 맞힌 개수가 같을 경우 계속해서 그다음으로 낮은 점수를 더 많이 맞힌 경우를 return 해주세요.
      • 예를 들어, [2,3,1,0,0,0,0,1,3,0,0]과 [2,1,0,2,0,0,0,2,3,0,0]를 비교하면 [2,1,0,2,0,0,0,2,3,0,0]를 return 해야 합니다.
      • 다른 예로, [0,0,2,3,4,1,0,0,0,0,0]과 [9,0,0,0,0,0,0,0,1,0,0]를 비교하면[9,0,0,0,0,0,0,0,1,0,0]를 return 해야 합니다.
  • 라이언이 우승할 방법이 없는 경우, return 할 정수 배열의 길이는 1입니다.
    • 라이언이 어떻게 화살을 쏘든 라이언의 점수가 어피치의 점수보다 낮거나 같으면 [-1]을 return 해야 합니다.

입출력 예

n info result
5 [2,1,1,1,0,0,0,0,0,0,0] [0,2,2,0,1,0,0,0,0,0,0]
1 [1,0,0,0,0,0,0,0,0,0,0] [-1]
9 [0,0,1,2,0,1,1,1,1,1,1] [1,1,2,0,1,2,2,0,0,0,0]
10 [0,0,0,0,0,0,0,0,3,4,3] [1,1,1,1,1,1,1,1,0,0,2]

풀이

과녁은 10점 -> 0점 으로 순차적으로 쏜다.

1) 현재 남은 화살의 개수 >= 어피치가 K점 과녁에 쏜 화살의 개수 + 1

      (1) 어피치가 K점 과녁에 쏜 화살의 개수 + 1

      (2) 화살을 쏘지 않고 넘어가는 경우

     두 가지 경우가 존재한다.

2) 현재 남은 화살의 개수 <= 어피치가 K점 과녁에 쏜 화살의 개수

     남은 화살을 모두 쏴도 어피치가 점수를 가져가게 되므로, 쏘지 않고 넘어간다.

3) 0점 과녁

    남은 화살이 존재 할 경우 모두 쏴야한다.

 

dfs로 완전 탐색을 구현한다.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<int> answer(1, -1);
int maxdiff = 0;

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

void calScore(vector<int> ryan, vector<int> apeach){
    int ryanScore = 0, apeachScore = 0;

    for(int i = 0; i < 11; i++){
        if(ryan[i] > apeach[i]){
            ryanScore += ( 10 - i);
        }
        else if(apeach[i] > 0){
            apeachScore += ( 10 - i);
        }
    }
    int diff = ryanScore - apeachScore;
    if(diff > 0 && maxdiff <= diff){
        if(maxdiff == diff && !cmp(ryan))   return;
        maxdiff = diff;
        answer = ryan;
    }
}

void dfs(int idx, int arrows, vector<int> ryan, vector<int> apeach){
    if(idx == 11 || arrows == 0){
        ryan[10] += arrows;
        calScore(ryan, apeach);
        ryan[10] -= arrows;
        return;
    }
    if(apeach[idx] < arrows){
        ryan[idx] += apeach[idx] + 1;
        dfs(idx + 1, arrows - apeach[idx] - 1, ryan, apeach);
        ryan[idx] -= apeach[idx] + 1;
    }
    dfs(idx+1, arrows, ryan, apeach);
}

vector<int> solution(int n , vector<int> info){
    vector<int> ryan(11 , 0);
    dfs(0 , n, ryan, info);
    if(answer.empty()){
        answer.push_back(-1);
    }

    return answer;
}

int main(){

    vector<int> info = {2,1,1,1,0,0,0,0,0,0,0};
    int n = 5;

    vector<int> result = solution(n, info);
    
    for(const auto &it : result){
        cout << it << " ";
    }
    
    return 0;
}

 

    다른 방법

int GetScore(const vector<int>& Apeach, const vector<int>& Ryan) {
	int ret = 0;
	for (int i = 0; i <= 10; i++) {
		if (!Apeach[i] && !Ryan[i]) continue;
		if (Apeach[i] < Ryan[i]) ret += 10 - i;
		else ret -= 10 - i;
	}
	return ret;
}

vector<int> solution(int n, vector<int> Apeach) {
	vector<int> ret, Ryan(11); int mx = 0;
	auto DFS = [&](int pos, int arrows, auto&& DFS) -> void {
		if (pos == -1 && arrows) return;
		if (arrows == 0) {
			const auto res = GetScore(Apeach, Ryan);
			if (res > mx) mx = res, ret = Ryan;
			return;
		}
		for (int i = arrows; i >= 0; i--) {
			Ryan[pos] = i;
			DFS(pos - 1, arrows - i, DFS);
			Ryan[pos] = 0;
		}
	};
	DFS(10, n, DFS);
	return mx ? ret : vector<int>{ -1 };
}
728x90