![]() |
途中経過
![]() |
答え
![]() |
線を引くときの基本
(線が交差しているからダメ)
![]() |
(線が枝分かれしているからダメ)
![]() |
(1の2辺に線が引かれているからダメ)
![]() |
(輪が2つに分かれたからダメ)
![]() |
これ以上確定しなくなったら、未確定な辺を任意に一つ選んで強制的に 確定させ、いわゆるバックトラックによって解を探索する。
このようにして書いたものが、 slither1.c である。これだと、簡単な問題は解けるが、少し規模が大きくなったり 複雑になったりすると計算時間が膨大になってしまう。
一方、人間がこのパズルを解く場合、上のルールだけでなく、 そのルールから論理的に導かれる「定理」を用いて効率的に 確定作業を行なって行く。例えば、
![]() |
のように3が隣同士に並んでいたら、
![]() |
のように5箇所の辺の状態が自動的に確定する。
ここでは、
![]() |
ならば | ![]() |
![]() |
ならば | ![]() |
![]() |
ならば | ![]() |
![]() |
ならば | ![]() |
![]() |
ならば | ![]() |
![]() |
ならば | ![]() |
![]() |
ならば | ![]() |
のルール群と、「そこを接続するとループになってしまう辺は接続しない」 というルールを加えて高速化を試みたものが、 slither2.c である。
両者の速度を、「ニコリ」1999年7月号の例題 ( ex0.dat, ex1.dat, ex2.dat, ex3.dat, ex4.dat, ex5.dat ) で比較すると、実行時間は
ex0 | ex1 | ex2 | ex3 | ex4 | ex5 |
0.0178 | 0.338 | 0.210 | 26.319 | 0.869 | ∞(14時間以上) |
0.0067 | 0.055 | 0.026 | 0.192 | 0.022 | 0.495 |
となり、「定理」による枝刈りがかなり有効であるようである。