ผลต่างระหว่างรุ่นของ "204512/บรรยาย 9"
Pattarika (คุย | มีส่วนร่วม) |
|||
(ไม่แสดง 20 รุ่นระหว่างกลางโดยผู้ใช้ 5 คน) | |||
แถว 1: | แถว 1: | ||
− | + | '''จดบันทึกคำบรรยายโดย''': <br/> | |
+ | พัทริกา ณ พิกุล 50653849<br/> | ||
+ | ศรณัฐ เจนถอมม้า 50653922<br/> | ||
+ | == Dynamic Programming == | ||
สมมุติต้องการเดินทางจากบ้าน ดช. ก ไปบ้าน ดญ. ข ระหว่างบ้าน ดช. ก กะ ดญ. ข ก็มีถนนตัดกันไปเรื่อยๆ | สมมุติต้องการเดินทางจากบ้าน ดช. ก ไปบ้าน ดญ. ข ระหว่างบ้าน ดช. ก กะ ดญ. ข ก็มีถนนตัดกันไปเรื่อยๆ | ||
แถว 6: | แถว 9: | ||
[[ภาพ:DP1.jpg]] | [[ภาพ:DP1.jpg]] | ||
+ | คำตอบคือ สามารถเลือกได้ | ||
<math>\begin{pmatrix} | <math>\begin{pmatrix} | ||
n+m \\ | n+m \\ | ||
m | m | ||
− | \end{pmatrix}</math> หรือ | + | \end{pmatrix}</math> แบบ หรือ |
<math>\begin{pmatrix} | <math>\begin{pmatrix} | ||
n+m \\ | n+m \\ | ||
n | n | ||
− | \end{pmatrix}</math> | + | \end{pmatrix}</math> แบบ |
+ | |||
C(m,n) = C(m-1, n) + C(m,n-1) | C(m,n) = C(m-1, n) + C(m,n-1) | ||
+ | |||
C(0,0) เลือกได้ 1 วิธี | C(0,0) เลือกได้ 1 วิธี | ||
+ | |||
C(x,y) = 0 ถ้า x<0 หรือ y<0 | C(x,y) = 0 ถ้า x<0 หรือ y<0 | ||
ในกรณีที่มีการ block เส้นทาง เราอาจจะเขียน pseudo code ได้ ให้ recursive ไปที่จุดที่ col-1, row-1 ไปเรื่อยๆ | ในกรณีที่มีการ block เส้นทาง เราอาจจะเขียน pseudo code ได้ ให้ recursive ไปที่จุดที่ col-1, row-1 ไปเรื่อยๆ | ||
+ | |||
วิธีหนึ่งที่ใช้หาเส้นทาง | วิธีหนึ่งที่ใช้หาเส้นทาง | ||
+ | |||
[[ภาพ:DP2.jpg]] | [[ภาพ:DP2.jpg]] | ||
วิธีนี้เราจะทำการมองไปที่ทุกจุด โดยค่าที่แต่ละจุดเกิดจากผลรวมน้ำหนักของโหนดก่อนหน้า ดังนั้นวิธีนี้ใช้เวลาเป็น O(mn) | วิธีนี้เราจะทำการมองไปที่ทุกจุด โดยค่าที่แต่ละจุดเกิดจากผลรวมน้ำหนักของโหนดก่อนหน้า ดังนั้นวิธีนี้ใช้เวลาเป็น O(mn) | ||
+ | |||
Dynamic programming คือการคำนวนมาก่อนเพื่อหาผลเฉลย | Dynamic programming คือการคำนวนมาก่อนเพื่อหาผลเฉลย | ||
[[Example]] | [[Example]] | ||
− | Function | + | |
+ | == Function Fibonacci == | ||
+ | |||
F(0) = F(1) = 1 | F(0) = F(1) = 1 | ||
+ | |||
F(1) = F(i-1) + F(i-2) เมื่อ i>1 | F(1) = F(i-1) + F(i-2) เมื่อ i>1 | ||
สังเกตว่ามันมีกรณีซ้ำซ้อนเกิดขึ้น | สังเกตว่ามันมีกรณีซ้ำซ้อนเกิดขึ้น | ||
− | F[0] | + | |
− | For i=2 to n do | + | F[0]<math>\gets</math>F[1]<math>\Leftarrow</math>1<br/> |
− | + | <br/> | |
− | Return F[n] | + | For i=2 to n do<br/> |
+ | F[i]<math>\gets</math>F[i-1] + F[i-2]<br/> | ||
+ | Return F[n]<br/> | ||
+ | |||
นั่นคือ ถ้าอยากรู้ f(i) ต้องรู้ f(i-1), f(i-2) | นั่นคือ ถ้าอยากรู้ f(i) ต้องรู้ f(i-1), f(i-2) | ||
[[ภาพ:DP3.jpg]] | [[ภาพ:DP3.jpg]] | ||
---- | ---- | ||
− | + | == Shortest path บน DAG (Directed Acyclic Graph)== | |
+ | เราหา shortest path อย่างไร จาก s<math>\to</math>t | ||
− | + | t อาจมีตัวติดกันมากมาย shortest path ที่มาจาก t<math>\to</math>s ได้ | |
− | t อาจมีตัวติดกันมากมาย shortest path ที่มาจาก | ||
ถ้ามีนผ่าน <math>v_1</math>, <math>v_2</math>, <math>v_3</math> พวกนี้ต้องเป็น shortest path ด้วยเช่นเดียวกัน | ถ้ามีนผ่าน <math>v_1</math>, <math>v_2</math>, <math>v_3</math> พวกนี้ต้องเป็น shortest path ด้วยเช่นเดียวกัน | ||
แถว 51: | แถว 67: | ||
<math>f(n) = min | <math>f(n) = min | ||
\begin{cases} | \begin{cases} | ||
− | D( | + | D(v_1) + l(v_1,t) \\ |
− | D( | + | D(v_2) + l(v_2,t) \\ |
− | D( | + | D(v_3) + l(v_3,t) |
\end{cases}</math> | \end{cases}</math> | ||
− | เราสามารถหาโดยไม่ต้องทำ recursive ก็ได้ โดยเรา evaluate ไปในทิศทางที่ขึ้นต่อกันเรื่อยๆ evaluate ด้วยลำดับที่เราเรียกว่า | + | เราสามารถหาโดยไม่ต้องทำ recursive ก็ได้ โดยเรา evaluate ไปในทิศทางที่ขึ้นต่อกันเรื่อยๆ evaluate ด้วยลำดับที่เราเรียกว่า tolopical order |
− | ถ้าเรียงลำดับตาม tolopical order (คือเป็น order ที่ edge | + | ถ้าเรียงลำดับตาม tolopical order (คือเป็น order ที่ edge ชี้จากโหนดน้อย->มาก)<br/> |
S = <math>v_0</math>, <math>v_1</math>, <math>v_2</math>, <math>v_3</math>, … , <math>v_n</math> | S = <math>v_0</math>, <math>v_1</math>, <math>v_2</math>, <math>v_3</math>, … , <math>v_n</math> | ||
+ | <br/> | ||
+ | For each <math>v_{i}</math>, <math>D(v_{1})</math> <math>\gets</math> infinity<br/> | ||
+ | <math>D(v_{0})</math> <math>\gets</math> 0<br/> | ||
+ | For i = 1,…,n:<br/> | ||
+ | <math>\qquad D(v_{i}) = \min_{Vj: (V_j, V_i) \in E} [D(V_j) + l(v_j,v_i)]</math> <br/> | ||
+ | |||
− | + | ขั้นตอนการแก้ปัญหา dynamic programming<br/> | |
− | + | 1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย)<br/> | |
− | + | 2. หาลำดับเพื่อ evaluate<br/> | |
− | + | 3. เขียน pseudo code<br/> | |
− | |||
− | |||
− | ขั้นตอนการแก้ปัญหา dynamic programming | ||
− | 1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย) | ||
− | 2. หาลำดับเพื่อ evaluate | ||
− | 3. เขียน pseudo code | ||
แถว 78: | แถว 94: | ||
เราอาจจะ plot เป็นตารางดังนี้ | เราอาจจะ plot เป็นตารางดังนี้ | ||
+ | |||
+ | [[ภาพ:DP5.jpg]] | ||
ตารางนี้เราทำการเก็บว่า ค่าไหนที่เกิดจากผลรวมของตัวมันบ้าง | ตารางนี้เราทำการเก็บว่า ค่าไหนที่เกิดจากผลรวมของตัวมันบ้าง | ||
แถว 85: | แถว 103: | ||
P(i) แทนจำนวนเหรียญที่เราใช้แล้วรวมกันได้ i บาท | P(i) แทนจำนวนเหรียญที่เราใช้แล้วรวมกันได้ i บาท | ||
− | P(i) = min P(i-1) + 1 | + | <math>P(i) = min |
− | + | \begin{cases} | |
− | + | P(i-1) + 1 \\ | |
+ | P(i-3) + 1 , & \mbox{if } i-3 >= 0\\ | ||
+ | P(i-4) + 1 , & \mbox{if } i-4 >= 0 | ||
+ | \end{cases}</math> | ||
ตัวอย่างนี้เราสามารถหาเหรียญที่ใช้น้อยที่สุดได้ | ตัวอย่างนี้เราสามารถหาเหรียญที่ใช้น้อยที่สุดได้ | ||
+ | |||
+ | [[ภาพ:DP6.jpg]] | ||
+ | |||
ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง | ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง | ||
+ | </math> | ||
+ | |||
+ | [[Example]] | ||
+ | |||
+ | มีถุงความจุเป็น L หน่วย<br/> | ||
+ | มีสินค้า k ประเภท<br/> | ||
+ | ประเภทที่ i, มีน้ำหนัก wi หน่วย<br/> | ||
+ | มีมูลค่า <math>v_{i}</math> หน่วย<br/> | ||
+ | <br/> | ||
+ | ให้หาสินค้าใส่ถุงโดย<br/> | ||
+ | 1. ความจุรวม = L<br/> | ||
+ | 2. มูลค่ารวมมากที่สุด<br/> | ||
+ | <br/> | ||
+ | เลือกสินค้าที่ i มา 1 ชิ้น จะได้ว่า<br/> | ||
+ | 1. <math>P(i) = \max_{j:w_j \le i} P(i-w_j) + V_j </math><br/> | ||
+ | 2. คำตอบคือ <math>\max_{i: i \le L} P(i)</math><br/> | ||
+ | *ต้องมี array ช่วยเหลือคอยเก็บค่า j<br/> | ||
+ | <math>A(i) = arg\min_{j: w_j \le i} P(i-w_j) + V_j</math><br/> | ||
+ | <br/> | ||
+ | อัลกอริทึมนี้ จะรันอยู่ในเวลา O(kL)<br/> | ||
+ | คำตอบนี้สำหรับปัญหาที่มี จำนวนสินค้าได้ไม่อั้น<br/> | ||
+ | แต่สำหรับสินค้าที่มี จำนวนกัด เราจะแก้ไขปัญหาได้อย่างไร<br/> | ||
+ | ปัญหาลักษณะนี้เราเรียกว่า Knapsack problem<br/> | ||
+ | |||
+ | <br/> | ||
+ | |||
+ | == Knapsack == | ||
+ | ถุงมีความจุ L หน่วย<br/> | ||
+ | มีของ k ชิ้น<br/> | ||
+ | ชิ้นที่ i หนัก <math>w_{i}</math>, มีมูลค่า <math>v_{L}</math><br/> | ||
+ | <br/> | ||
+ | ต้องการหาเซตของ ของ ที่<br/> | ||
+ | (1) น้ำหนักรวมของ ของ รวมไม่เกิน L<br/> | ||
+ | (2) มีมูลค่ารวมมากที่สุด<br/> | ||
+ | *ต้องจัดลำดัับการหยิบให้ดี เพราะ ของแต่ละแบบมีชิ้นเดียว<br/> | ||
+ | '''hint:''' มีตัวแปร 2 ตัว<br/> | ||
+ | <br/> | ||
+ | [[sol]]<br/> | ||
+ | จัดการหยิบของให้มีลำดับ<br/> | ||
+ | เอาของชิ้นที่ 1 -> หยิบ | ||
+ | -> ไม่่หยิบ | ||
+ | เอาของชิ้นที่ 2 -> หยิบ | ||
+ | -> ไม่่หยิบ | ||
+ | เอาของชิ้นที่ 3 -> หยิบ | ||
+ | -> ไม่่หยิบ | ||
+ | . | ||
+ | . | ||
+ | . | ||
+ | เอาของชิ้นที่ n -> หยิบ | ||
+ | -> ไม่่หยิบ | ||
+ | ให้<br/> | ||
+ | <math>A(i,j)</math> แทนมูลค่ามากที่สุดที่ทำได้เมื่อน้ำหนักรวม = i และใช้ของไม่เกินชิ้นที่ j<br/> | ||
+ | <math>A(i,j) = max | ||
+ | \begin{cases} | ||
+ | A(i,j-1) \\ | ||
+ | v_{j}+A(i-w_{j},j-1), & \mbox{if } i \ge w_{j} | ||
+ | \end{cases}</math><br/> | ||
+ | <br/> | ||
+ | [[ภาพ:DP7.jpg]] | ||
+ | <br/> | ||
− | + | <table border=1 cellspacing=0> | |
+ | <tr><th>ชิ้นที่</th><th>น้ำหนัก</th><th>มูลค่า</th></tr> | ||
+ | <tr><td> 1 </td><td> 7 </td><td> 8 </td></tr> | ||
+ | <tr><td> 2 </td><td> 4 </td><td> 5 </td></tr> | ||
+ | <tr><td> 3 </td><td> 4 </td><td> 5 </td></tr> | ||
+ | <tr><td> 4 </td><td> 2 </td><td> 3 </td></tr> | ||
+ | <tr><td> 5 </td><td> 1 </td><td> 1 </td></tr> | ||
+ | </table><br/> | ||
+ | <br/> | ||
− | + | == Longest Common Substring == | |
− | + | ให้ string S, T <br/> | |
− | + | ต้องการหา substring U ที่มีความยาวมากที่สุดที่เป็นทั้ง substring ของ S และ T <br/> | |
− | + | [[sol]] <br/> | |
+ | string A เป็น substring ของ B<br/> | ||
+ | ถ้าเราสามารถสร้าง A ได้โดยการลบตัวอักษรบางตัวจาก B (หรือไม่ลบก็ได้)<br/> | ||
+ | <br/> | ||
+ | ให้ n = |S| , m = |T| <br/> | ||
+ | S = AAGGATTCCAAGGAAAAGTTAG <br/> | ||
+ | T = GGTCCAGCCCAGCCATTGCAGTT <br/> | ||
+ | <br/> | ||
+ | [[ภาพ:DP8.jpg]] | ||
+ | <br/> | ||
+ | สำหรับ string S ใดๆ <br/> | ||
+ | ให้ <math>S_{i}</math> แทน prefix ความยาว i ของ S<br/> | ||
+ | [[Example]]<br/> | ||
+ | <math>S_{5}</math> = AAGGA<br/> | ||
+ | T = GGT<br/> | ||
+ | หา longest common substring ของ <math>S_{n}</math> กับ <math>T_{m}</math><br/> | ||
+ | <br/> | ||
+ | L(i,j) = ความยาวของ longest common substring ของ <math>S_{i}</math> กับ <math>T_{i}</math> <br/> | ||
+ | [[ภาพ:DP12.jpg]]<br/> | ||
+ | <math>L(i,j) = max | ||
+ | \begin{cases} | ||
+ | L(i,j-1) \\ | ||
+ | L(i-1,j) \\ | ||
+ | L(i-1,j-1)+1, & \mbox{if } S[i] = T[j]\\ | ||
+ | L(i-1,j-1), & \mbox{if } S[i] \ne T[j] \quad (optional \; case) | ||
+ | \end{cases}</math><br/> | ||
+ | <br/> | ||
+ | [[ทดลอง fill ตาราง]]<br/> | ||
+ | [[ภาพ:DP9.jpg]]<br/> | ||
+ | ใช้เวลา O(mn)<br/> | ||
+ | <br/> | ||
− | + | == Optimal Binary Search Tree == | |
− | |||
− | + | <table border=1 cellspacing=0> | |
− | 1. | + | <tr><th>Data</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th></tr> |
− | + | <tr><th>Access</th><td>3</td><td>2000</td><td>4</td><td>2</td><td>10</td><td>5</td><td>10000</td></tr> | |
− | + | </table><br/> | |
− | + | ถ้า access ข้อมูลทุกๆตัวเท่าๆกันจะได้ tree ดังนี้<br/> | |
− | + | [[ภาพ:DP10.jpg]]<br/> | |
− | + | แต่ถ้า access ข้อมูลตามตารางที่ให้มาจะได้ tree ดังนี้<br/> | |
− | + | [[ภาพ:DP13.jpg]]<br/> | |
− | + | '''ตัวอย่าง'''<br/> | |
+ | มีข้อมูล 1,...,n<br/> | ||
+ | ข้อมูล i ถูก access <math>f_{i}</math> ครั้ง<br/> | ||
+ | ต้องการสร้าง BST ที่มีค่าใช้จ่ายในการ access น้อยที่สุด<br/> | ||
+ | '''hint : '''subproblem มี index 2 ตัว<br/> | ||
+ | <br/> | ||
+ | [[sol]]<br/> | ||
+ | ให้ B(i,j) = ค่าใช้จ่ายในการ access ของ tree ที่ดีทีุ่สุดของข้อมูลตั้งแต่ i,...,j<br/> | ||
+ | <math>B(i,j) = \min_{k} f_{k} + B(i,k-1) + B(k+1,j) + \sum_{l=1,l \ne k}^j f_{l}</math><br/> | ||
+ | <math>B(i,j) = \min_{k} \sum_{l=1}^j f_{l} + B(i,k-1) + B(k+1,j)</math><br/> | ||
+ | B(i,j) = 0 if i>j<br/> | ||
+ | <br/> | ||
+ | [[สมมติ]]<br/> | ||
+ | B(1,5)<br/> | ||
+ | B(2,5), B(1,1), B(3,5)<br/> | ||
+ | B(1,2), B(4,5)<br/> | ||
+ | B(1,3), B(5,5)<br/> | ||
+ | B(1,4)<br/> | ||
+ | [[ภาพ:DP11.jpg]] | ||
+ | เป็นลูป 3 ชั้น ใ้ช้เวลา <math>O(n^3)</math> |
รุ่นแก้ไขปัจจุบันเมื่อ 10:23, 5 มีนาคม 2553
จดบันทึกคำบรรยายโดย:
พัทริกา ณ พิกุล 50653849
ศรณัฐ เจนถอมม้า 50653922
เนื้อหา
Dynamic Programming
สมมุติต้องการเดินทางจากบ้าน ดช. ก ไปบ้าน ดญ. ข ระหว่างบ้าน ดช. ก กะ ดญ. ข ก็มีถนนตัดกันไปเรื่อยๆ คำถามคือ จากบ้าน ดช. ก ไปยังบ้าน ดญ.ข สามารถเดินทางโดยใช้เส้นทางต่างกันได้กี่แบบ
คำตอบคือ สามารถเลือกได้ แบบ หรือ แบบ
C(m,n) = C(m-1, n) + C(m,n-1)
C(0,0) เลือกได้ 1 วิธี
C(x,y) = 0 ถ้า x<0 หรือ y<0
ในกรณีที่มีการ block เส้นทาง เราอาจจะเขียน pseudo code ได้ ให้ recursive ไปที่จุดที่ col-1, row-1 ไปเรื่อยๆ
วิธีหนึ่งที่ใช้หาเส้นทาง
วิธีนี้เราจะทำการมองไปที่ทุกจุด โดยค่าที่แต่ละจุดเกิดจากผลรวมน้ำหนักของโหนดก่อนหน้า ดังนั้นวิธีนี้ใช้เวลาเป็น O(mn)
Dynamic programming คือการคำนวนมาก่อนเพื่อหาผลเฉลย
Function Fibonacci
F(0) = F(1) = 1
F(1) = F(i-1) + F(i-2) เมื่อ i>1
สังเกตว่ามันมีกรณีซ้ำซ้อนเกิดขึ้น
F[0]F[1]1
For i=2 to n do
F[i]F[i-1] + F[i-2]
Return F[n]
นั่นคือ ถ้าอยากรู้ f(i) ต้องรู้ f(i-1), f(i-2)
Shortest path บน DAG (Directed Acyclic Graph)
เราหา shortest path อย่างไร จาก st
t อาจมีตัวติดกันมากมาย shortest path ที่มาจาก ts ได้ ถ้ามีนผ่าน , , พวกนี้ต้องเป็น shortest path ด้วยเช่นเดียวกัน
ถ้ามองแบบ recursive เราจะค่อยคลี่ออกแล้วมองปัญหาย่อยๆ
เราสามารถหาโดยไม่ต้องทำ recursive ก็ได้ โดยเรา evaluate ไปในทิศทางที่ขึ้นต่อกันเรื่อยๆ evaluate ด้วยลำดับที่เราเรียกว่า tolopical order
ถ้าเรียงลำดับตาม tolopical order (คือเป็น order ที่ edge ชี้จากโหนดน้อย->มาก)
S = , , , , … ,
For each , infinity
0
For i = 1,…,n:
ขั้นตอนการแก้ปัญหา dynamic programming
1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย)
2. หาลำดับเพื่อ evaluate
3. เขียน pseudo code
ถ้าเรามีเหรียญ 3, 5 บาท เราจะประกอบเหรียญให้เป็นเงินจำนวนไม่เกิน 100 บาท ได้กี่วิธี (ใช้เหรียญกี่เหรียญก็ได้)
เราอาจจะ plot เป็นตารางดังนี้
ตารางนี้เราทำการเก็บว่า ค่าไหนที่เกิดจากผลรวมของตัวมันบ้าง ซึ่งอาจจะให้ผลดีขึ้นถ้าเราเก็บด้วยว่าเราใช้เหรียญไปกี่เหรียญ
Example P(i) แทนจำนวนเหรียญที่เราใช้แล้วรวมกันได้ i บาท
ตัวอย่างนี้เราสามารถหาเหรียญที่ใช้น้อยที่สุดได้
ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง </math>
มีถุงความจุเป็น L หน่วย
มีสินค้า k ประเภท
ประเภทที่ i, มีน้ำหนัก wi หน่วย
มีมูลค่า หน่วย
ให้หาสินค้าใส่ถุงโดย
1. ความจุรวม = L
2. มูลค่ารวมมากที่สุด
เลือกสินค้าที่ i มา 1 ชิ้น จะได้ว่า
1.
2. คำตอบคือ
- ต้องมี array ช่วยเหลือคอยเก็บค่า j
อัลกอริทึมนี้ จะรันอยู่ในเวลา O(kL)
คำตอบนี้สำหรับปัญหาที่มี จำนวนสินค้าได้ไม่อั้น
แต่สำหรับสินค้าที่มี จำนวนกัด เราจะแก้ไขปัญหาได้อย่างไร
ปัญหาลักษณะนี้เราเรียกว่า Knapsack problem
Knapsack
ถุงมีความจุ L หน่วย
มีของ k ชิ้น
ชิ้นที่ i หนัก , มีมูลค่า
ต้องการหาเซตของ ของ ที่
(1) น้ำหนักรวมของ ของ รวมไม่เกิน L
(2) มีมูลค่ารวมมากที่สุด
- ต้องจัดลำดัับการหยิบให้ดี เพราะ ของแต่ละแบบมีชิ้นเดียว
hint: มีตัวแปร 2 ตัว
sol
จัดการหยิบของให้มีลำดับ
เอาของชิ้นที่ 1 -> หยิบ -> ไม่่หยิบ เอาของชิ้นที่ 2 -> หยิบ -> ไม่่หยิบ เอาของชิ้นที่ 3 -> หยิบ -> ไม่่หยิบ . . . เอาของชิ้นที่ n -> หยิบ -> ไม่่หยิบ
ให้
แทนมูลค่ามากที่สุดที่ทำได้เมื่อน้ำหนักรวม = i และใช้ของไม่เกินชิ้นที่ j
ชิ้นที่ | น้ำหนัก | มูลค่า |
---|---|---|
1 | 7 | 8 |
2 | 4 | 5 |
3 | 4 | 5 |
4 | 2 | 3 |
5 | 1 | 1 |
Longest Common Substring
ให้ string S, T
ต้องการหา substring U ที่มีความยาวมากที่สุดที่เป็นทั้ง substring ของ S และ T
sol
string A เป็น substring ของ B
ถ้าเราสามารถสร้าง A ได้โดยการลบตัวอักษรบางตัวจาก B (หรือไม่ลบก็ได้)
ให้ n = |S| , m = |T|
S = AAGGATTCCAAGGAAAAGTTAG
T = GGTCCAGCCCAGCCATTGCAGTT
สำหรับ string S ใดๆ
ให้ แทน prefix ความยาว i ของ S
Example
= AAGGA
T = GGT
หา longest common substring ของ กับ
L(i,j) = ความยาวของ longest common substring ของ กับ
ทดลอง fill ตาราง
ใช้เวลา O(mn)
Optimal Binary Search Tree
Data | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
Access | 3 | 2000 | 4 | 2 | 10 | 5 | 10000 |
ถ้า access ข้อมูลทุกๆตัวเท่าๆกันจะได้ tree ดังนี้
แต่ถ้า access ข้อมูลตามตารางที่ให้มาจะได้ tree ดังนี้
ตัวอย่าง
มีข้อมูล 1,...,n
ข้อมูล i ถูก access ครั้ง
ต้องการสร้าง BST ที่มีค่าใช้จ่ายในการ access น้อยที่สุด
hint : subproblem มี index 2 ตัว
sol
ให้ B(i,j) = ค่าใช้จ่ายในการ access ของ tree ที่ดีทีุ่สุดของข้อมูลตั้งแต่ i,...,j
B(i,j) = 0 if i>j
สมมติ
B(1,5)
B(2,5), B(1,1), B(3,5)
B(1,2), B(4,5)
B(1,3), B(5,5)
B(1,4)