差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン最新のリビジョン両方とも次のリビジョン | ||
programming_algorithm:contest_history:atcoder:2019:0106_educational_dp [2019/01/16] – ikatakos | programming_algorithm:contest_history:atcoder:2019:0106_educational_dp [2019/01/18] – ikatakos | ||
---|---|---|---|
行 1: | 行 1: | ||
- | ======Educational DP Contest I, | + | ======Educational DP Contest I,J, |
[[https:// | [[https:// | ||
行 61: | 行 61: | ||
===== J - Sushi ===== | ===== J - Sushi ===== | ||
- | [[https:// | + | [[https:// |
==== 問題 ==== | ==== 問題 ==== | ||
行 105: | 行 105: | ||
&+& \frac{j}{N} DP[i+1][j-1][k] \\ | &+& \frac{j}{N} DP[i+1][j-1][k] \\ | ||
&+& \frac{k}{N} DP[i][j+1][k-1] \\ | &+& \frac{k}{N} DP[i][j+1][k-1] \\ | ||
- | &+& 1 \\ | + | &+& 1 |
+ | \end{eqnarray} | ||
+ | \begin{eqnarray} | ||
DP[i][j][k] &=& \frac{N}{i+j+k}(\frac{i}{N} DP[i-1][j][k] \\ | DP[i][j][k] &=& \frac{N}{i+j+k}(\frac{i}{N} DP[i-1][j][k] \\ | ||
&+& \frac{j}{N} DP[i+1][j-1][k] \\ | &+& \frac{j}{N} DP[i+1][j-1][k] \\ | ||
&+& \frac{k}{N} DP[i][j+1][k-1] \\ | &+& \frac{k}{N} DP[i][j+1][k-1] \\ | ||
&+& 1) \\ | &+& 1) \\ | ||
- | DP[i][j][k] | + | |
\end{eqnarray} | \end{eqnarray} | ||
行 117: | 行 119: | ||
$i+j+k$ が小さい方からループを回せばボトムアップでもできるし、このように+1、-1が入り交じってどの値から先に埋めれば良いか混乱する場合は、メモ化再帰でもよい。 | $i+j+k$ が小さい方からループを回せばボトムアップでもできるし、このように+1、-1が入り交じってどの値から先に埋めれば良いか混乱する場合は、メモ化再帰でもよい。 | ||
- | リスト参照が多いため、Python, PyPyだと制限時間が厳しい。諦めて%%C++%%などを使う。 | + | === 言語事情 === |
+ | |||
+ | リスト参照が多いため、Pythonだと制限時間が厳しい。 | ||
+ | |||
+ | Pythonでは変数に何でも入れられるため普段あまり意識しないが、データ型の概念はしっかりとある。 | ||
+ | 変数を扱うたびに「この変数の型はなんぞや」のチェックから入るのが、Pythonが便利な反面、遅い一因となっている(要出典)。 | ||
+ | |||
+ | PyPyでは、事前の型推論によりチェックを一部省略することで高速化を図っている部分があるが、処理の中でintもfloatも取り得る変数にしてしまうとその推論が上手く働かない。 | ||
+ | |||
+ | 今回のように小数が入るとわかっている場合は、初期化する値も小数にしておけば、よりPyPyの恩恵を享受できる、とのこと。 | ||
+ | * [[https:// | ||
<sxh python> | <sxh python> | ||
- | # TLE | ||
from collections import Counter | from collections import Counter | ||
行 129: | 行 140: | ||
total = c1 + 2 * c2 + 3 * c3 | total = c1 + 2 * c2 + 3 * c3 | ||
c23 = c2 + c3 | c23 = c2 + c3 | ||
- | dp = [[[0] * (c3 + 1) for _ in range(c2 + c3 + 1)] for _ in range(n + 2)] | + | dp = [[[0.0] * (c3 + 1) for _ in range(c2 + c3 + 1)] for _ in range(n + 2)] # ←ここを0で初期化するとTLE |
for k in range(1, n + 1): | for k in range(1, n + 1): | ||
行 241: | 行 252: | ||
$DP[l][r]$ があった時、先頭と末尾のどちらを取るかは、以下の大きい方となる。 | $DP[l][r]$ があった時、先頭と末尾のどちらを取るかは、以下の大きい方となる。 | ||
- | * $-DP[l-1][r]+a_l$ | + | * $-DP[l+1][r]+a_l$ |
* $-DP[l][r-1]+a_{r-1}$ | * $-DP[l][r-1]+a_{r-1}$ | ||