Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AOJ 0557 A First Grader 解説
Search
kagamiz
March 30, 2013
0
900
AOJ 0557 A First Grader 解説
OkNCT-ICT 2013 春合宿 Day 6 (らしい) に解説したもの.
kagamiz
March 30, 2013
Tweet
Share
More Decks by kagamiz
See All by kagamiz
KCS v2. の開発
kagamiz
0
210
internship final presentation
kagamiz
0
1.2k
internship-middle term presentation
kagamiz
0
980
すうがくのまほう
kagamiz
0
310
ご当地料理の紹介
kagamiz
0
320
オンラインジャッジシステムの実装
kagamiz
0
1.1k
AOJ 0022 Maximum Sum Sequence 解説
kagamiz
1
1.5k
JOI2013 本選1 Illumination 解説
kagamiz
0
290
AOJ 0186 Aizu Chicken 解説
kagamiz
0
260
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
352
28k
Designing with Data
zakiwarfel
96
4.8k
RailsConf 2023
tenderlove
4
540
Why You Should Never Use an ORM
jnunemaker
PRO
51
8.6k
Done Done
chrislema
178
15k
A Tale of Four Properties
chriscoyier
151
22k
Designing Experiences People Love
moore
136
23k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
227
16k
Statistics for Hackers
jakevdp
789
220k
A designer walks into a library…
pauljervisheath
200
23k
Intergalactic Javascript Robots from Outer Space
tanoku
266
26k
KATA
mclloyd
15
12k
Transcript
AOJ 0557 A First Grader 解説 @kagamiz
www.company.com 問題概要 • 長さがn の数列が与えられます. • 途中計算が0 以上20 以下になり, 最後がa[n]
と等しく なるように間に+ か – を入れてください. • n ≦ 100, 0 ≦ a[i] ≦ 20
www.company.com 入力例の解析 • n = 11 数列 = {8 3 2 4 8 7 2 4 0 8 8} •
8+3-2-4+8-7-2-4-0+8=8 • 8+3-2-4+8-7-2-4+0+8=8 • 8+3+2+4-8-7+2-4-0+8=8 • 8+3+2+4-8-7+2-4+0+8=8 • 8+3-2-4+8-7+2+4-0-8=8 • 8+3-2-4+8-7+2+4+0-8=8 • 8-3+2+4-8+7+2+4-0-8=8 • 8-3+2+4-8+7+2+4+0-8=8 • 8-3+2-4+8+7+2-4-0-8=8 • 8-3+2-4+8+7+2-4+0-8=8 • …の10 個
www.company.com 入力例の解析 • n = 40 数列 = {1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1} • もうなんかヤバそう • 全探索お姉さんなら数え上げ兼ねないけど... (http://www.youtube.com/watch?v=Q4gTV4r0zRs) • どうやら7069052760 個あるらしい. JOI くんマジキチ. • ちなみにint 型には入りません. ザンネン.
www.company.com O(2^n) 解法 • がんばって再帰で+と-を入れていく. • どうやるのが楽? → 引数に(今の項数, 今の和)を持つ
と行けそう. • 擬似コード function getNum(int index, int sum){ if (index + 1 == N) return (sum == a[index + 1]); return (getNum(index + 1, sum a[index + 1]) + – getNum(index + 1, sum + a[index + 1]); }
www.company.com O(2^n) 解法 • 例外処理がたくさん • 最初の項は必ず+ だったり • 負になるところとか20
を越える所を排除したり • 満点解法を思いつくには, この(今の項数, 今の和) のよ うな状態を思いつくことがとても大事.
www.company.com O(ns) 解法 • さっきまでのプログラムの何が無駄だったか? • 同じ状態を何度も遷移すること. • これってどうすれば解消出来たっけ? →
Dynamic Programming, しよう(提案)
www.company.com O(ns) 解法 – (1) メモ化 • さっきまでのプログラムの何が無駄だったか? • 同じ状態を何度も遷移すること.
• メモ化することで同じ状態にこないようにしよう. • 引数の状態は高々(100, 21) = 2100 通り. いける.
www.company.com O(ns) 解法 – (1) メモ化 • メモ化することで同じ状態にこないようにしよう. • 引数の状態は高々(100,
21) = 2100 通り. いける. • メモ化配列memo[100][21] を用意すると簡単. • 擬似コード int memo[100][21]; function getNum(int index, int sum){ if (~memo[index][sum]) then return (memo[index][sum]); if (index + 1 == N) return (sum == a[index + 1]); return (memo[index][sum] = getNum(index + 1, sum a[index + – 1]) + getNum(index + 1, sum + a[index + 1]); }
www.company.com O(ns) 解法 – (1) メモ化 • 通例メモ化配列は-1 で初期化することが多い •
メモされていない状態, ということを指す • 初期条件をあまり意識しなくて良いので楽と言う人が 結構居る • @kyuridenamida さんとか
www.company.com O(ns) 解法 – (2) for 文 • さっきの配列を考えると, dp[1][a[1]]
は明らかに1. • この”明らか” を拡張していく事を考える. • 1 から順番に, 前の値を利用していくと自然とn 番目に ついての答えも求まる. • ちなみに, 答えはn – 1番目までの項で, 和がa[n] となっ ているものなので, dp[n – 1][a[n]] となる.
www.company.com O(ns) 解法 – (2) for 文 dp[1][seq[1]] = 1;
for (i = 2; i <= n; i++){ for (j = 0; j <= 20; j++){ if (j + seq[i] <= 20){ dp[i][j + seq[i]] += dp[i - 1][j]; } if (j - seq[i] >= 0){ dp[i][j - seq[i]] += dp[i - 1][j]; } } }
www.company.com O(ns) 解法 – (2) for 文 • こういう風に, 計算した値を後の方に再利用するDP
を 配るDP と言う. • 今着目している値に操作するDP を貰うDP を言う.
www.company.com DP について • DP は “習うより慣れろ” が鉄則です. • こういう記事とか,
蟻本の練習問題をたくさん解きま しょう. • DP の練習として良いやつ http://d.hatena.ne.jp/kyuridenamida/20111009/1318091499 • 「DP・メモ化再帰」はこんなに簡単だった http://www.itmedia.co.jp/enterprise/articles/1003/06/news002.html • 動的計画法を学ぶリソース・練習問題まとめ http://d.hatena.ne.jp/cou929_la/20100708/1278600922