Judge

Programmers - 양궁대회

깡구_ 2022. 7. 6. 23:14

title: Programmers - 양궁대회
date: 2022-07-06
tags:

  • Algorithm
  • DFS
  • BruteForce




https://school.programmers.co.kr/learn/courses/30/lessons/92342


문제 요약

어피치가 어드밴티지를 가지는 양궁 대회이다. 어피치가 먼저 화살을 쐈고, 라이언은 어피치의 화살을 보고 가장 높은 점수차이가 나도록 쏴야 한다.
어떻게 쏘더라도 라이언이 우승할 수 없다면 -1을, 가능하다면 화살을 vector에 넣어 return한다.


문제 풀이

문제를 잘 읽자
문제를 잘못 읽어서 한시간 가까이 삽질하였다.
우선 과녁은 11개이며, 라이언은 어피치가 쏜 화살보다 많이 과녁에 맞춰야 점수를 얻을 수 있다.
라이언의 입장에서 점수를 얻거나, 혹은 아예 쏘지 않고 얻지 않는 두 가지 경우로 구분할 수 있다.
2^11 = 2048으로, 경우의 수가 적기 때문에 완전 탐색을 해도 된다.
점수의 차이가 많이 나는 것이 중요하므로 greedy한 접근은 정답을 찾을 수 없다.

해당 문제는 라이언의 점수가 가장 큰 경우가 아닌, 어피치와의 점수 차이가 가장 큰 경우를 구하는 것이다.
매 상황에서 라이언과 어피치의 점수를 계산하는 것은 오히려 성능 저하가 예상되었고, 이로 인하여 점수는 정답을 구할 때에만 계산한다.

최대 2048가지만 확인하면 되기에 .data 함수가 없더라도 성능 측면에서 문제는 없을 것이다.


프로그램

#include <vector>

using std :: vector ;

int * ipTemp ;
int * ipInfo ;
int * ipAnswer ;
int iMaxGap ;

void Score ()
{
    int iGap = 0 ;

    for ( int i = 0 ; i < 11 ; ++i )
    {
        if ( 0 == ipTemp [ i ] + ipInfo [ i ] )
            continue ;

        iGap += ( ipTemp [ i ] > ipInfo [ i ] ) ? 10 - i : i - 10 ;
    }

    if ( iGap < iMaxGap )
        return ;

    if ( iMaxGap < iGap )
    {
        for ( int i = 0 ; i < 11 ; ++i )
        {
            ipAnswer [ i ] = ipTemp [ i ] ;
        }

        iMaxGap = iGap ;
    }
    else
    {
        for ( int i = 10 ; i >= 0 ; --i )
        {
            if ( ipTemp [ i ] < ipAnswer [ i ] )            // Answer is better, ignore this
                return ;
            else if ( ipTemp [ i ] > ipAnswer [ i ] )        // Current is better, update
                break ;
        }
        for ( int i = 0 ; i < 11 ; ++i )
        {
            ipAnswer [ i ] = ipTemp [ i ] ;
        }
    }
}

void DFS ( int iIndex , int iArrowLeft )
{
    if ( ( 0 == iArrowLeft ) || ( 11 == iIndex ) )
    {
        ipTemp [ 10 ] += iArrowLeft ;
        Score () ;
        ipTemp [ 10 ] = 0 ;

        return ;
    }

    if ( ipInfo [ iIndex ] + 1 <= iArrowLeft )                // Take this score
    {
        ipTemp [ iIndex ] = ipInfo [ iIndex ] + 1 ;

        DFS ( iIndex + 1 , iArrowLeft - ipTemp [ iIndex ] ) ;

        ipTemp [ iIndex ] = 0 ;
        ipTemp [ 10 ] = 0 ;
    }

    DFS ( iIndex + 1 , iArrowLeft ) ;                        // Ignore this score
    ipTemp [ 10 ] = 0 ;
}

vector < int > solution ( int n , vector < int > info )
{
    vector < int > answer ( 11 , 0 ) ;
    vector < int > vTemp ( 11 , 0 ) ;
    int iSum = 0 ;



    ipTemp = vTemp.data () ;
    ipInfo = info.data () ;
    ipAnswer = answer.data () ;
    iMaxGap = 0 ;

    for ( int i = 0 ; i < 11 ; ++i )
    {
        iSum += ( 0 != ipInfo [ i ] ) ? ipInfo [ i ] : 0 ;
    }
    DFS ( 0 , n ) ;

    if ( 0 == iMaxGap )
        return { -1 } ;


    return answer ;
}