AOJ0232について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taiki_okano
記事: 5
登録日時: 9年前

AOJ0232について

#1

投稿記事 by taiki_okano » 9年前

AOJ0232(http://judge.u-aizu.ac.jp/onlinejudge/d ... sp?id=0232)について、全てのサンプルテストは通るのですが、1個目からRuntime errorとして弾かれてしまいます。そこで、最大サイズの入力(X = 4, Y = 50, Z = 49, イベントマスは全て+100ポイント)を入力してみたのですが、問題なく処理出来ました。clangとgccでコンパイルして同じ結果でした。
何が間違っているのか、ご教授願います。

コード:

#include <cstdio>
#include <algorithm>

constexpr int MAX_X = 4, MAX_YN = 50, MAX_Z = 49;

int main(){
    while(true){
        int X, Y, Z;
        int roulette[MAX_X], jump[MAX_YN]{}, get_money[MAX_YN]{};
        float dp[MAX_YN + 1][100 * MAX_Z + 1]{1};
        scanf("%d%d%d", &X, &Y, &Z);
        if(!X){
            break;
        }
        for(int i = 0; i < X; ++i){
            scanf("%d", &roulette[i]);
        }
        for(int i = 0; i < Z; ++i){
            int n, e, a;
            scanf("%d%d%d", &n, &e, &a);
            switch(e){
                case 1:
                    jump[n] = a;
                    break;
                case 2:
                    get_money[n] = a;
                    break;
                case 3:
                    get_money[n] = -a;
                    break;
            }
        }
        for(int i = 0; i < Y; ++i){
            for(int j = 0; j <= i * 100; ++j){
                if(dp[i][j] == 0){
                    continue;
                }
                if(jump[i] > 0){
                    dp[std::min(i + jump[i], Y)][j] += dp[i][j];
                    continue;
                }
                for(int k = 0; k < X; ++k){
                    dp[std::min(i + roulette[k], Y)][std::max(j + get_money[i + roulette[k]], 0)] += dp[i][j] / X;
                }
            }
        }
        float ans = 0;
        for(int i = 0; i <= 100 * Y; ++i){
            ans += dp[Y][i] * i;
        }
        printf("%d\n", (int)ans);
    }
    return 0;
}

taiki_okano
記事: 5
登録日時: 9年前

Re: AOJ0232について

#2

投稿記事 by taiki_okano » 9年前

コード:

#include <cstdio>
#include <cmath>
#include <algorithm>

constexpr int MAX_X = 4, MAX_YN = 50, MAX_Z = 49;

int main(){
    while(true){
        int X, Y, Z;
        int roulette[MAX_X], jump[MAX_YN]{}, get_money[MAX_YN]{};
        float dp[MAX_YN + 1][100 * MAX_Z + 1]{1};
        scanf("%d%d%d", &X, &Y, &Z);
        if(!X){
            break;
        }
        for(int i = 0; i < X; ++i){
            scanf("%d", &roulette[i]);
        }
        for(int i = 0; i < Z; ++i){
            int n, e, a;
            scanf("%d%d%d", &n, &e, &a);
            switch(e){
                case 1:
                    jump[n] = a;
                    break;
                case 2:
                    get_money[n] = a;
                    break;
                case 3:
                    get_money[n] = -a;
                    break;
            }
        }
        for(int i = 0; i < Y; ++i){
            for(int j = 0; j <= i * 100; ++j){
                if(dp[i][j] == 0){
                    continue;
                }
                if(jump[i] > 0){
                    dp[std::min(i + jump[i], Y)][j] += dp[i][j];
                    continue;
                }
                for(int k = 0; k < X; ++k){
                    dp[std::min(i + roulette[k], Y)][std::max(j + get_money[std::min(i + roulette[k], Y)], 0)] += (dp[i][j] / X);
                }
            }
        }
        float ans = 0;
        for(int i = 0; i <= 100 * Y; ++i){
            ans += dp[Y][i] * i;
        }
        printf("%d\n", int(floor(ans)));
    }
    return 0;
}
のようにしてi+roulette[k]をstd::minで0と比較することで、メモリの範囲外アクセスは解決したのですが、これでもまだWrong Answerとでてしまいます。
どなたかご教授願います。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: AOJ0232について

#3

投稿記事 by みけCAT » 9年前

float (doubleですらない!) を使っているから、誤差が出るのではないでしょうか?
試していませんが、X倍した値を用いて整数で計算するといいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

taiki_okano
記事: 5
登録日時: 9年前

Re: AOJ0232について

#4

投稿記事 by taiki_okano » 9年前

返信、ありがとうございます。

しかし、最後にintに切り捨ててしまうので、float doubleの違いではなさそうです。

一応、あのコードでなぜ動かないのかはわからなかったのですが、一度すべて消して一から書き直したところ、うまくいってしまったので、それで今回は諦めます。

コード:

#include <cstdio>
#include <algorithm>

constexpr int MAX_X = 4, MAX_Y = 50;

int main(){
    while(true){
        int X, Y, Z;
        int roulette[MAX_X], jump[MAX_Y]{}, get_money[MAX_Y]{};
        float dp[MAX_Y + 1][100 * MAX_Y + 1]{1};
        scanf("%d%d%d", &X, &Y, &Z);
        if(!X){
            break;
        }
        for(int i = 0; i < X; ++i){
            scanf("%d", &roulette[i]);
        }
        for(int i = 0; i < Z; ++i){
            int n, e, a;
            scanf("%d%d%d", &n, &e, &a);
            switch(e){
                case 1:
                    jump[n] = a;
                    break;
                case 2:
                    get_money[n] = a;
                    break;
                case 3:
                    get_money[n] = -a;
                    break;
            }
        }
        for(int i = 0; i < Y; ++i){
            for(int j = 0; j <= 100 * MAX_Y; ++j){
                if(dp[i][j] == 0){
                    continue;
                }
                for(int k = 0; k < X; ++k){
                    int ni, nj;
                    ni = std::min(i + roulette[k], Y);
                    nj = std::max(j + get_money[ni], 0);
                    ni = std::min(ni + jump[ni], Y);
                    dp[ni][nj] += dp[i][j] / X;
                }
            }
        }
        float ans = 0;
        for(int i = 0; i <= 100 * MAX_Y; ++i){
            ans += dp[Y][i] * i;
        }
        printf("%d\n", (int)ans);
    }
    return 0;
}

ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る