ผลต่างระหว่างรุ่นของ "204512/บรรยาย 9"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
 
(ไม่แสดง 20 รุ่นระหว่างกลางโดยผู้ใช้ 5 คน)
แถว 1: แถว 1:
[[Dynamic Programming]]
+
'''จดบันทึกคำบรรยายโดย''': <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 revolenchy
+
 
 +
== 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]F[1]1
+
 
For i=2 to n do
+
F[0]<math>\gets</math>F[1]<math>\Leftarrow</math>1<br/>
F[i]F[i-1] + F[i-2]
+
<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 บน DAG (Directed Acyclic Graph)==
 +
เราหา shortest path อย่างไร จาก s<math>\to</math>t
  
เราหา shortest path อย่างไร จาก st
+
t อาจมีตัวติดกันมากมาย shortest path ที่มาจาก t<math>\to</math>s ได้
t อาจมีตัวติดกันมากมาย shortest path ที่มาจาก ts ได้
 
 
ถ้ามีนผ่าน <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(v1) + l(v1,t) \\
+
D(v_1) + l(v_1,t) \\
D(v2) + l(v2,t) \\
+
D(v_2) + l(v_2,t) \\
D(v3) + l(v3,t)
+
D(v_3) + l(v_3,t)
 
\end{cases}</math>
 
\end{cases}</math>
  
  
เราสามารถหาโดยไม่ต้องทำ recursive ก็ได้ โดยเรา evaluate ไปในทิศทางที่ขึ้นต่อกันเรื่อยๆ evaluate ด้วยลำดับที่เราเรียกว่า tropical order
+
เราสามารถหาโดยไม่ต้องทำ 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/>
 +
                     
  
Foreach vi, D(v1)  infinity
+
ขั้นตอนการแก้ปัญหา dynamic programming<br/>
D(v0)  0
+
1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย)<br/>
For I = 1,…,n:
+
2. หาลำดับเพื่อ evaluate<br/>
D(vi) = min [D(Vj) + l(vj,vi)]
+
3. เขียน pseudo code<br/>
                      Vj: (Vj, Vi) E E
 
 
 
ขั้นตอนการแก้ปัญหา 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  
                P(i-3) + 1 if i-3 >= 0
+
\begin{cases}
                P(i-4) + 1   i-4 >= 0
+
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/>
  
[[Example]]
+
<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/>
  
มีถุงความจุเป็น L หน่วย
+
== Longest Common Substring ==
มีสินค้า k ประเภท
+
ให้ string S, T <br/>
ประเภทที่ i, มีน้ำหนัก wi หน่วย
+
ต้องการหา substring U ที่มีความยาวมากที่สุดที่เป็นทั้ง substring ของ S และ T <br/>
มีมูลค่า vi หน่วย
+
[[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/>
  
ให้หาสินค้าใส่ถุงโดย 1. ความจุรวม = L
+
== Optimal Binary Search Tree ==
2. มูลค่ารวมมากที่สุด
 
  
เลือกสินค้าที่ i มา 1 ชิ้น จะได้ว่า
+
<table border=1 cellspacing=0>
1. P(i) = max P(i-wj) + Vj  j:wj <= i
+
<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>
2. คำตอบคือ max P(i)
+
<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>
                  i: i <= L
+
</table><br/>
A(i) = arg min P(i-wj) + Vj
+
ถ้า access ข้อมูลทุกๆตัวเท่าๆกันจะได้ tree ดังนี้<br/>
อัลกอริทึมนี้ จะรันอยู่ในเวลา O(kL)
+
[[ภาพ:DP10.jpg]]<br/>
คำตอบนี้สำหรับปัญหาที่มี จำนวนสินค้าได้ไม่อั้น
+
แต่ถ้า access ข้อมูลตามตารางที่ให้มาจะได้ tree ดังนี้<br/>
แต่สำหรับสินค้าที่มี จำนวนกัด เราจะแก้ไขปัญหาได้อย่างไร
+
[[ภาพ:DP13.jpg]]<br/>
ปัญหาลักษณะนี้เราเรียกว่า Knapsack problem
+
'''ตัวอย่าง'''<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

สมมุติต้องการเดินทางจากบ้าน ดช. ก ไปบ้าน ดญ. ข ระหว่างบ้าน ดช. ก กะ ดญ. ข ก็มีถนนตัดกันไปเรื่อยๆ คำถามคือ จากบ้าน ดช. ก ไปยังบ้าน ดญ.ข สามารถเดินทางโดยใช้เส้นทางต่างกันได้กี่แบบ

DP1.jpg

คำตอบคือ สามารถเลือกได้ แบบ หรือ แบบ

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 ไปเรื่อยๆ

วิธีหนึ่งที่ใช้หาเส้นทาง

DP2.jpg

วิธีนี้เราจะทำการมองไปที่ทุกจุด โดยค่าที่แต่ละจุดเกิดจากผลรวมน้ำหนักของโหนดก่อนหน้า ดังนั้นวิธีนี้ใช้เวลาเป็น O(mn)

Dynamic programming คือการคำนวนมาก่อนเพื่อหาผลเฉลย

Example

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) DP3.jpg


Shortest path บน DAG (Directed Acyclic Graph)

เราหา shortest path อย่างไร จาก st

t อาจมีตัวติดกันมากมาย shortest path ที่มาจาก ts ได้ ถ้ามีนผ่าน , , พวกนี้ต้องเป็น shortest path ด้วยเช่นเดียวกัน

ถ้ามองแบบ recursive เราจะค่อยคลี่ออกแล้วมองปัญหาย่อยๆ

DP4.jpg


เราสามารถหาโดยไม่ต้องทำ 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


Example

ถ้าเรามีเหรียญ 3, 5 บาท เราจะประกอบเหรียญให้เป็นเงินจำนวนไม่เกิน 100 บาท ได้กี่วิธี (ใช้เหรียญกี่เหรียญก็ได้)

เราอาจจะ plot เป็นตารางดังนี้

DP5.jpg

ตารางนี้เราทำการเก็บว่า ค่าไหนที่เกิดจากผลรวมของตัวมันบ้าง ซึ่งอาจจะให้ผลดีขึ้นถ้าเราเก็บด้วยว่าเราใช้เหรียญไปกี่เหรียญ

Example P(i) แทนจำนวนเหรียญที่เราใช้แล้วรวมกันได้ i บาท

ตัวอย่างนี้เราสามารถหาเหรียญที่ใช้น้อยที่สุดได้

DP6.jpg

ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง </math>

Example

มีถุงความจุเป็น 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


DP7.jpg

ชิ้นที่น้ำหนักมูลค่า
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

DP8.jpg
สำหรับ string S ใดๆ
ให้ แทน prefix ความยาว i ของ S
Example
= AAGGA
T = GGT
หา longest common substring ของ กับ

L(i,j) = ความยาวของ longest common substring ของ กับ
DP12.jpg


ทดลอง fill ตาราง
DP9.jpg
ใช้เวลา O(mn)

Optimal Binary Search Tree

Data1234567
Access320004210510000


ถ้า access ข้อมูลทุกๆตัวเท่าๆกันจะได้ tree ดังนี้
DP10.jpg
แต่ถ้า access ข้อมูลตามตารางที่ให้มาจะได้ tree ดังนี้
DP13.jpg
ตัวอย่าง
มีข้อมูล 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)

DP11.jpg เป็นลูป 3 ชั้น ใ้ช้เวลา