はまやんはまやんはまやん

hamayanhamayan's blog

UNOシミュレータ [yukicoder No.769]

https://yukicoder.me/problems/no/769

解説

https://yukicoder.me/submissions/307913

色々な変数を定義して、シミュレーションをしよう。
cards[i] := プレイヤーiが何個のカードを出したか
cu := 現在のプレイヤー
dir := 現在の方向(1か-1)
draw2 := ドロー2で蓄積されているカード
draw4 := ドロー4で蓄積されているカード
pre := 現在の1つ前のプレイヤー(答えを求めるのに使う)
dirを1,-1としているのが、cu += dirと書くことができるためである。
 
まずドロー系の蓄積がある場合は、手を出す前にドローで引かせて、スキップするので、それを処理する。
次にカードを使わせて、使ったカードに応じて、処理を行う。
cu = (cu + N) % Nとすることで、必ず0~N-1に丸めて使う。
最後は一番最後にカードを使ったプレイヤーが勝利プレイヤーになるので、preを持ってくる。

int N, M;
int cards[101010];
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N >> M;

    int cu = 0, dir = 1, draw2 = 0, draw4 = 0, pre;
    rep(m, 0, M) {
        string l; cin >> l;
        if (0 < draw2 and l != "drawtwo") {
            cards[cu] -= draw2;
            cu += dir;
            draw2 = 0;
        }
        if (0 < draw4 and l != "drawfour") {
            cards[cu] -= draw4;
            cu += dir;
            draw4 = 0;
        }
        cu = (cu + N) % N;

        cards[cu]++;

        pre = cu;
        if (l == "number") cu += dir;
        else if (l == "drawtwo") {
            draw2 += 2;
            cu += dir;
        }
        else if (l == "drawfour") {
            draw4 += 4;
            cu += dir;
        }
        else if (l == "skip") cu += dir * 2;
        else {
            dir *= -1;
            cu += dir;
        }

        cu = (cu + N) % N;
    }
    cu = pre;

    printf("%d %d\n", cu + 1, cards[cu]);
}