程式設計也快樂第3期SQL程式碼

lt發表於2013-04-10

設計思路:設x和y分別是6升和5升壺裡剩餘的水,用窮舉法,每一步各有6種操作可選,即:

5升去取水、6升去池取水、5升倒掉、6升倒水至5升、5升倒水至6升、6升倒掉,分別編號1-6

一邊試探,一邊記錄,找到符合條件的一個結果後,通過日誌的字首匹配,將它的歷史記錄取出

with o as(
select level l from dual connect by level<=6) --操作編號
,t(lv,m,x,y) as(select 1, cast('0' as varchar(30)) , 0, 0 from dual --m記錄倒水日誌
union all
select lv+1,m||l,
case l 
when 1 then x    --5升去池取水
when 2 then 6    --6升去池取水
when 3 then x    --5升倒掉
when 4 then case when x-(5-y)>=0 then x-(5-y) else 0 end --6升倒水至5升
when 5 then case when y-(6-x)>=0 then 6 else x+y end   --5升倒水至6升
when 6 then 0    --6升倒掉
end,
case l 
when 1 then 5
when 2 then y 
when 3 then 0 
when 4 then case when x-(5-y)>=0 then 5 else x+y end
when 5 then case when y-(6-x)>=0 then y-(6-x) else 0 end
when 6 then y 
end
from t,o where l<>substr(m,-1) and
(substr(m,-1),l) not in ((1,2),(2,1),(1,3),(2,6),(3,6),(6,3),(4,5),(5,4))
 and x<>3 and y<>3 and lv<=10 and x between 0 and 6 and y between 0 and 5) 
--操作條件:一個壺不做連續相同操作、還沒有完成、最多操作10次,不能出現負數
select * from t where substr((select m from t t1 where (x=3 or y=3) and rownum<=1),1,lv)=t.m order by lv;
--將符合條件的一個結果的歷史記錄取出

    LV M                                       X          Y

     1 0                                       0          0
     2 01                                      0          5
     3 015                                     5          0
     4 0151                                    5          5
     5 01515                                   6          4
     6 015156                                  0          4
     7 0151565                                 4          0
     8 01515651                                4          5
     9 015156515                               6          3

已選擇9行。

相關文章