Google Code Jam Japan 2011 Qual A: カードシャッフル
問題概要
カードをある手順にしたがってシャッフルして、最後に特定の位置にあるカードを答える問題。
考えたこと
- (今回は時間の余裕もあるしD言語を試すことにした)
- これはよくある問題。終了状態から逆にシミュレーションして最初どこにあったのかを答えれば良い。
- これでlargeとsmallの両方書いてもいいんだけどそれだと練習にならないのでsmallは愚直にシミュレーションで書く。
- 配列のスライス書きやすくていい感じだ。
通ったコード
small
import std.stdio; int nextInt(){ int x; scanf("%d",&x); return x; } int solve(){ int M = nextInt, C = nextInt, W = nextInt; int[] cards = new int[M]; foreach(int i, ref x ; cards){ x = i + 1; } for(auto i=0; i<C; i++){ auto A = nextInt - 1, B = nextInt; cards = cards[A..A+B] ~ cards[0..A] ~ cards[A+B..$]; } return cards[W-1]; } void main(){ for(auto c = 1, T = nextInt; c <= T; c++){ writef("Case #%d: %d\n", c, solve()); } }
large
import std.stdio; int nextInt(){ int x; scanf("%d",&x); return x; } int solve(){ int M = nextInt, C = nextInt, W = nextInt; int r = W; //処理を記憶 int[] As, Bs; for(int i=0; i<C; i++){ As ~= nextInt; Bs ~= nextInt; } //終了状態から初期状態へのシミュレーション for(auto i=C-1; i>=0; i--){ auto A = As[i], B = Bs[i]; if( r <= B ){ r += A - 1; } else if( r < A + B ){ r -= B; } } return r; } void main(){ for(auto c = 1, T = nextInt; c <= T; c++){ writef("Case #%d: %d\n", c, solve()); } }