ผลต่างระหว่างรุ่นของ "204512/บรรยาย 9"
Pattarika (คุย | มีส่วนร่วม) |
|||
แถว 42: | แถว 42: | ||
สังเกตว่ามันมีกรณีซ้ำซ้อนเกิดขึ้น | สังเกตว่ามันมีกรณีซ้ำซ้อนเกิดขึ้น | ||
− | F[0] | + | F[0]<-F[1]<=1<br/> |
− | For i=2 to n do | + | <br/> |
− | + | For i=2 to n do<br/> | |
− | Return F[n] | + | F[i]<-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) | ||
แถว 71: | แถว 72: | ||
เราสามารถหาโดยไม่ต้องทำ recursive ก็ได้ โดยเรา evaluate ไปในทิศทางที่ขึ้นต่อกันเรื่อยๆ evaluate ด้วยลำดับที่เราเรียกว่า tropical order | เราสามารถหาโดยไม่ต้องทำ recursive ก็ได้ โดยเรา evaluate ไปในทิศทางที่ขึ้นต่อกันเรื่อยๆ evaluate ด้วยลำดับที่เราเรียกว่า tropical 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/> | |
− | Foreach vi, D(v1) | + | Foreach vi, D(v1) <- infinity<br/> |
− | D(v0) | + | D(v0) <- 0<br/> |
− | For I = 1,…,n: | + | For I = 1,…,n:<br/> |
− | D(vi) = min [D(Vj) + l(vj,vi)] | + | D(vi) = min [D(Vj) + l(vj,vi)]<br/> |
Vj: (Vj, Vi) E E | Vj: (Vj, Vi) E E | ||
− | ขั้นตอนการแก้ปัญหา dynamic programming | + | ขั้นตอนการแก้ปัญหา dynamic programming<br/> |
− | 1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย) | + | 1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย)<br/> |
− | 2. หาลำดับเพื่อ evaluate | + | 2. หาลำดับเพื่อ evaluate<br/> |
− | 3. เขียน pseudo code | + | 3. เขียน pseudo code<br/> |
แถว 108: | แถว 109: | ||
ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง | ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง | ||
− | + | </math> | |
[[Example]] | [[Example]] | ||
− | มีถุงความจุเป็น L หน่วย | + | มีถุงความจุเป็น L หน่วย<br/> |
− | มีสินค้า k ประเภท | + | มีสินค้า k ประเภท<br/> |
− | + | ประเภทที่ i, มีน้ำหนัก wi หน่วย<br/> | |
− | + | มีมูลค่า vi หน่วย<br/> | |
− | + | <br/> | |
− | ให้หาสินค้าใส่ถุงโดย 1. ความจุรวม = L | + | ให้หาสินค้าใส่ถุงโดย<br/> |
− | + | 1. ความจุรวม = L<br/> | |
− | + | 2. มูลค่ารวมมากที่สุด<br/> | |
− | เลือกสินค้าที่ i มา 1 ชิ้น จะได้ว่า | + | <br/> |
+ | เลือกสินค้าที่ i มา 1 ชิ้น จะได้ว่า<br/> | ||
1. P(i) = max P(i-wj) + Vj j:wj <= i | 1. P(i) = max P(i-wj) + Vj j:wj <= i | ||
2. คำตอบคือ max P(i) | 2. คำตอบคือ max P(i) | ||
i: i <= L | i: i <= L | ||
− | A(i) = arg min P(i-wj) + Vj | + | A(i) = arg min P(i-wj) + Vj<br/> |
− | อัลกอริทึมนี้ จะรันอยู่ในเวลา O(kL) | + | <br/> |
− | คำตอบนี้สำหรับปัญหาที่มี จำนวนสินค้าได้ไม่อั้น | + | อัลกอริทึมนี้ จะรันอยู่ในเวลา O(kL)<br/> |
− | แต่สำหรับสินค้าที่มี จำนวนกัด เราจะแก้ไขปัญหาได้อย่างไร | + | คำตอบนี้สำหรับปัญหาที่มี จำนวนสินค้าได้ไม่อั้น<br/> |
− | ปัญหาลักษณะนี้เราเรียกว่า Knapsack problem | + | แต่สำหรับสินค้าที่มี จำนวนกัด เราจะแก้ไขปัญหาได้อย่างไร<br/> |
+ | ปัญหาลักษณะนี้เราเรียกว่า Knapsack problem<br/> | ||
+ | |||
+ | <br/> | ||
+ | [[Knapstack]]<br/> | ||
+ | ถุงมีความจุ 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 >= w_{j} | ||
+ | \end{cases}</math> | ||
+ | ตาราง L?????? |
รุ่นแก้ไขเมื่อ 07:09, 15 สิงหาคม 2550
สมมุติต้องการเดินทางจากบ้าน ดช. ก ไปบ้าน ดญ. ข ระหว่างบ้าน ดช. ก กะ ดญ. ข ก็มีถนนตัดกันไปเรื่อยๆ คำถามคือ จากบ้าน ดช. ก ไปยังบ้าน ดญ.ข สามารถเดินทางโดยใช้เส้นทางต่างกันได้กี่แบบ
คำตอบคือ สามารถเลือกได้ แบบ หรือ แบบ
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 revolenchy
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 ด้วยลำดับที่เราเรียกว่า tropical order
ถ้าเรียงลำดับตาม tolopical order (คือเป็น order ที่ edge ชี้จากโหนดน้อย->มาก)
S = , , , , … ,
Foreach vi, D(v1) <- infinity
D(v0) <- 0
For I = 1,…,n:
D(vi) = min [D(Vj) + l(vj,vi)]
Vj: (Vj, Vi) E E
ขั้นตอนการแก้ปัญหา dynamic programming
1. เขียน recurrence (เริ่มต้นนิยามปัญหาย่อย)
2. หาลำดับเพื่อ evaluate
3. เขียน pseudo code
ถ้าเรามีเหรียญ 3, 5 บาท เราจะประกอบเหรียญให้เป็นเงินจำนวนไม่เกิน 100 บาท ได้กี่วิธี (ใช้เหรียญกี่เหรียญก็ได้)
เราอาจจะ plot เป็นตารางดังนี้
ตารางนี้เราทำการเก็บว่า ค่าไหนที่เกิดจากผลรวมของตัวมันบ้าง ซึ่งอาจจะให้ผลดีขึ้นถ้าเราเก็บด้วยว่าเราใช้เหรียญไปกี่เหรียญ
Example P(i) แทนจำนวนเหรียญที่เราใช้แล้วรวมกันได้ i บาท
ตัวอย่างนี้เราสามารถหาเหรียญที่ใช้น้อยที่สุดได้
ถ้าถามต่ออีกว่า เราจะรู้ได้หรือไม่ ว่าใช้เหรียญอะไรไปบ้าง? วิธีการคือ เราจะเก็บ pointer ไว้ เพื่อดูว่าค่าผลรวมได้มาจากการรวมเหรียญไหนไปบ้าง </math>
มีถุงความจุเป็น L หน่วย
มีสินค้า k ประเภท
ประเภทที่ i, มีน้ำหนัก wi หน่วย
มีมูลค่า vi หน่วย
ให้หาสินค้าใส่ถุงโดย
1. ความจุรวม = L
2. มูลค่ารวมมากที่สุด
เลือกสินค้าที่ i มา 1 ชิ้น จะได้ว่า
1. P(i) = max P(i-wj) + Vj j:wj <= i
2. คำตอบคือ max P(i)
i: i <= L
A(i) = arg min P(i-wj) + Vj
อัลกอริทึมนี้ จะรันอยู่ในเวลา O(kL)
คำตอบนี้สำหรับปัญหาที่มี จำนวนสินค้าได้ไม่อั้น
แต่สำหรับสินค้าที่มี จำนวนกัด เราจะแก้ไขปัญหาได้อย่างไร
ปัญหาลักษณะนี้เราเรียกว่า Knapsack problem
Knapstack
ถุงมีความจุ L หน่วย
มีของ k ชิ้น
ชิ้นที่ i หนัก , มีมูลค่า
ต้องการหาเซตของ ของ ที่
(1) น้ำหนักรวมของ ของ รวมไม่เกิน L
(2) มีมูลค่ารวมมากที่สุด
- ต้องจัดลำดัับการหยิบให้ดี เพราะ ของแต่ละแบบมีชิ้นเดียว
hint: มีตัวแปร 2 ตัว
sol
จัดการหยิบของให้มีลำดับ
เอาของชิ้นที่ 1 -> หยิบ -> ไม่่หยิบ เอาของชิ้นที่ 2 -> หยิบ -> ไม่่หยิบ เอาของชิ้นที่ 3 -> หยิบ -> ไม่่หยิบ . . . เอาของชิ้นที่ n -> หยิบ -> ไม่่หยิบ
ให้
แทนมูลค่ามากที่สุดที่ทำได้เมื่อน้ำหนักรวม = i และใช้ของไม่เกินชิ้นที่ j
ตาราง L??????