四人過橋問題的SQL解法

yangtingkun發表於2012-04-18

看了開發版的帖子,又沒有忍住,簡單寫了一個SQL語句。關於問題的詳細描述可以參考http://www.itpub.net/thread-1595264-1-1.html

 

 

傳說中的微軟面試題:

有一群人A,B,C,D (人數>=2)要在夜裡走過獨木橋過河,他們只有一把手電筒。四個人的速度不同,過河分別需要1,2,5,10分鐘,橋上最多走兩個人,兩個人一起走時按速度慢的計算。過河一定要用手電筒。請問最快的方法是如何安排,需要幾分鐘?

例子輸出:

A B,A,A C,A,A D  19

直接給出最終結果:

SQL> WITH C AS
  2  (SELECT NAME, TIME, POWER(2, ROWNUM - 1) POS FROM BRIDGE_CROSSING),
  3  A AS
  4  (SELECT 0 RN, A.NAME || ' ' || B.NAME NAME, GREATEST(A.TIME, B.TIME) TIME, A.POS + B.POS POS
  5  FROM C A, C B
  6  WHERE A.NAME < B.NAME
  7  UNION ALL
  8  SELECT 1, NAME, TIME, POS FROM C),
  9  B (RN, NAME, TIME, POS) AS
 10  (SELECT 0 RN, CAST ('' AS VARCHAR2(4000)) NAME, 0, 0 POS FROM DUAL
 11  UNION ALL
 12  SELECT B.RN + 1,
 13     B.NAME || ',' || A.NAME,
 14     B.TIME + A.TIME,
 15     DECODE(MOD(B.RN, 2), 0, B.POS + A.POS, B.POS - A.POS)
 16  FROM B, A
 17  WHERE MOD(B.RN, 2) = A.RN
 18  AND DECODE(MOD(B.RN, 2), 0, BITAND(B.POS, A.POS), BITAND(B.POS - A.POS, A.POS)) = 0)
 19  SELECT LTRIM(NAME, ',') NAME, TIME FROM
 20  (SELECT NAME, TIME, RANK() OVER(ORDER BY TIME) RN
 21  FROM B
 22  WHERE POS = POWER(2, 4) - 1)
 23  WHERE RN = 1;

NAME                                 TIME
------------------------------ ----------
A B,A,C D,B,A B                        17
A B,B,C D,A,A B                        17

簡單描述一下思路,透過構造一個POS列標識每個人的位置,比如1101表明ABD三個人都已經過橋了,如果POS的值達到15,則說明所有人都過橋。

這個遞迴WITH和以往的區別在於,兩個人一起過橋和一個人回來送手電的處理規則是不同的,甚至連線資料都是不同的。這裡採用將兩個人過橋和一個人回來作為不同的記錄插入到同一個表中,然後用不同的ID進行區別。隨後的遞迴呼叫,無論是查詢列,還是進行關聯的時候都要進行條件的判斷,判斷當前是兩個人過橋,還是一個人回來,從而進行不同的操作。

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-721858/,如需轉載,請註明出處,否則將追究法律責任。

相關文章