全探索と計算量の見積もり
この記事の内容
可能性をすべて試すプログラム(全探索)と計算量の見積もりについて書きます。
目次
問題の大きさの把握
数値の表現
通常C++では、整数はint型の変数で表現します。int型では、231 ~ 2*109 くらいまでの数を表現できるので、それより大きな数を扱うときは、long long 型を使用します。(210 = 1024 ~ 103を覚えておくとよいでしょう。)
符号付き整数の表現
type | bits | 下限 | 上限 | 備考 |
---|---|---|---|---|
int | 32 | -231 | 231 - 1 | 約20億 |
long | 32/64 | 非推奨 | ||
long long | 64 | -263 | 263 -1 | C++から標準形 |
_int128_t | 128 | gcc拡張 |
各型で表現可能な範囲は環境によって異なりうります。
時間と空間の制約
競技プログラミングで出題される各問題には、実行時間と利用可能メモリについての制約も付加されています。
プログラムの実行時間やメモリの使用量は、(1)実行環境、(2)問題の大きさ、(3)アルゴリズムによって大きく変わりうります。
(1)の実行環境については、通常競技プログラミング側の実行環境は、十分高速なので、手元で効率的に動くことが確認できたら大丈夫です。また(2)の問題の大きさについても、問題になることはほとんどないです。競技プログラミングにおいては(あるいは普通のプログラミングにおいても)、(3)のアルゴリズムについてがどのような役割を果たすかが、最も重要な話題です。
組み合わせを試す
コンピュータが得意な解法はすべての組み合わせを力づくで試すことです。実際多くの問題はそれで解くことができます。全ての可能性を試すためには、for文を用いたり、再帰を用いたりします。
計算量の簡単な検討
for文が最大何回回るかを考えることで、計算量を見積もることができます。C++で大体1秒間のどれくらいの計算ができるかは、下の表の通りなので、問題を解くときの目安にしてください。
演算回数 | コメント |
---|---|
1 000 000 | 余裕をもって実行可能 |
10 000 000 | 多分可能 |
100 000 000 | とてもシンプルな演算なら可能 |
この表の数値は実行環境によって変わりますが、最近の多くのコンピュータのCPUは、1GHz(109)程度で動作しているので、CPUが100サイクル以内にできる演算なら、1秒間に107回程度まではおそらく実行可能と期待できます。
演算によってサイクル数は異なり、たとえば、メモリ参照やnew/deleteは、単純な算術演算よりそれぞれ10倍,100倍程度遅いです。
試行回数の見積もりと計算の手順の改良
下の例題を参考にして、計算方法の微調整により、計算量が異なることを見ていきます。
例題:Space Coconut Crab
宇宙ヤシガニの出現場所を探す.エネルギー E が観測されたとして,出現場所の候補は,x + y2 + z3 = E を満たす整数座標 (x, y, z) で,さらに x + y + z の値が最小の場所に限られるという.x + y + z の最小値を求めよ.(x, y, z は非負の整数,E は正の整数で 1, 000, 000 以下,宇
宙ヤシガニは,宇宙最大とされる甲殻類であり,成長後の体長は 400 メートル以上,足を広げれば 1, 000 メートル以上 ← 同じ数値でも重要な制約と余計な情報の区別に注意)
(http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2012 より)
まず次のような方針を考える。
- 方針1:変数x,y,zのすべてのパターンを調べ、それが条件を満たすかどうかを調べる。
この場合どれくらいの計算量が必要かを見積もってみましょう。x,y,zの動く範囲は、それぞれ、x:[0,E],y:[0,E^{1/2}],z:[0,E^{1/3}]です。Eの最大値が106 より、最大での計算量が必要です。これは、制限時間の8秒以内には終わりそうにありません。
したがって別の方針を考える必要があります。
方針2:xとyのみを考え、からzを決定する。 この場合は、(x, y)の組のみを考えれば良いので、計算量のオーダーは、で済みます。
方針3:上の方針2で動かす変数をx,zにする。 この場合は、計算量のオーダーは、となり、方針2よりも計算量を減らせています。
方針4:方針2で動かす変数をy,zにする。 この場合は、計算量のオーダーは、となり、方針3よりもさらに計算量を減らせています。
このようにどのような方針で問題にアプローチするか(アルゴリズムの選択)によって大幅に必要な計算量は変わるので、計算手順の改良は問題を解くうえで非常に重要です。