STARCRAFT 문제에 대해서 여쭙고 싶은게 있습니다.

  • 작은광대
    작은광대

    #include
    #include
    #include
    #include

    int facto(int n) {
    if ( n == 1 || n==0 ) return 1;
    else return n*facto(n-1);
    }

    int permutation( int n, int k ) {
    int res = 1;
    //if ( k== 0 ) return 1;
    for (k ; k != 0 ; k-- ) {
    res *= (n-k+1);
    }
    return res;
    }

    int combination( int n, int k ) {
    int res = 1;
    if ( n-k < k ) { k = n-k; }
    return permutation(n,k)/facto(k);
    }

    double calcLose( int totalGame, int loseGame, double percent ) {
    double numoflose= (double)(combination(totalGame,loseGame)) ;
    double loseper=pow((100-percent)/100, loseGame) ;
    return numoflose*loseper;
    }

    int roundddd( double db ) {
    int tmp = (db*1000);
    //printf("\t\t%d\n", tmp);
    if ( tmp < 0 ) {
    exit(0);
    }

    if ( tmp%10 <4 ) { return (int)(db*100); }
    else { return (int)(db*100+1); }

    }

    int main() {
    int i_case = 0;
    int percent = 0, winning = 0;

    scanf("%d", &i_case);
    
    for ( int i = 0 ; i < i_case ; ++i ) {
        scanf("%d %d",&percent, &winning);
        //printf("%d %d",percent, winning);
        {
            int totalGame = 2*winning-1;
            double totalWinper = 0;
            double winper = pow((double)percent/100.0,winning);
            printf("%f\n", winper);
            for ( int i = 0 ; i < winning ; ++i ) {
                double temp = calcLose(winning-1+i,i,percent)*winper;
                totalWinper += temp;
                printf("\t%f\n", temp);
            }
            printf("%d\n", roundddd(totalWinper));
        }
    
    }
    
    
    
    return 0;

    }


    위와 같이 코딩했습니다.

    아무리 생각해도 알고리즘의 문제는 아닌 것 같고,
    실수를 연산하는 과정에서 계산 값이 달라지는게 아닌가 싶은데요,
    ( 실제로 수가 좀 커지니까 0.008이 나와야 될 값이 0.002가 나오더라구요)

    이런 경우에는 최대한 실수형을 사용하지 않는 쪽으로 코딩을 하는 것이 맞는 건가요?
    실제로 대회에서는 어떤 식으로 계산하는지 궁금합니다.


    13년 전
4개의 댓글이 있습니다.
  • astein
    astein

    일단 간단하게 봤는데 roundddd 함수가 틀린 것 같네요~
    if ( tmp%10 <4 ) 로 되어 있으면 tmp % 10 == 4일때 올림을 해 버리겠네요.


    13년 전 link
  • Taeyoon_Lee
    Taeyoon_Lee

    실제 대회에서는 실수연산을 피할 수 있다면, 최대한 실수형을 사용하지 않는 게 바람직하지만,
    이 문제는 역으로 갑니다. 최대한 실수형을 사용해서 계산합니다. 소수 첫째 자리에서 반올림을 해야 하기 때문에, 반올림 차이로 답이 갈리는 경우는 나오기 어렵습니다. (실제로 가능한 모든 입력에서 반올림이 문제되는 경우는 없습니다.)


    13년 전 link
  • 작은광대
    작은광대

    astein // 그건 제 실수네요ㅠ 고맙습니다.ㅎ

    Taeyoon_Lee // 19판 10선승제의 경우, 확률이 50%일때, 10승 9패로 승리하는 경우에는 계산해보면 0.0088인데 프로그램 결과에서는 0.002가 나와서 이런 질문을 드렸습니다. 일단 문제는 그렇군요ㅠ 고맙습니다.ㅎ


    13년 전 link
  • 작은광대
    작은광대

    Taeyoon_Lee // 변수가 오버플로우 됐었더군요; 제가 잠깐 정신을 놨나봅니다.ㅠ 허접한 질문에 답변 고맙습니다.


    13년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.