programming.in.th · ข้อ 2041
ต้องออกจากเมือง 1 แล้วกลับมาให้พอดี T วัน โดย T ถึงพันล้าน ถนนยาวไม่เกิน 5 วัน จึงหั่นเมืองเป็นสำเนาให้ทุกถนนยาวหนึ่งวันเท่ากัน แล้วเดินทีละวันกลายเป็นคูณเมทริกซ์บนพีชคณิต max-plus ยกกำลังแบบทวิภาคข้ามช่วงที่ไม่มีเทศกาล
อาณาจักรเอลฟ์มี N เมือง เมืองที่ i ทำอาหารที่ให้ความพึงพอใจ C[i] หน่วย
ถนนในอาณาจักรเป็นทางเดียวทั้งหมด M เส้น ถนนเส้นหนึ่งพาจากเมือง u ไปเมือง v
และใช้เวลา w วัน ออกจาก u วันที่ d ก็ไปถึง v วันที่ d + w
นักชิม W เริ่มที่เมือง 1 ในวันที่ 0 และต้องกลับมารายงานตัวที่เมือง 1 ในวันที่ T พอดี ห้ามหยุดพักระหว่างทาง
พอถึงเมืองไหนเขาชิมทันทีแล้วออกเดินทางต่อในวันนั้นเลย กลับมาเมืองเดิมกี่รอบก็ได้ความพึงพอใจเท่าเดิมทุกรอบ
นอกจากนี้ยังมีเทศกาลอาหาร k งาน งานที่ i จัดวันที่ t ที่เมือง x
ถ้าเขาอยู่ที่เมืองนั้นพอดีวันนั้นก็ได้เพิ่มอีก y หน่วย เราต้องบอกว่าความพึงพอใจรวมที่มากที่สุดเป็นเท่าไร
อินพุต / ขอบเขต / เอาต์พุต
N M T k บรรทัดที่สองคือ C[1..N]
ต่อด้วย M บรรทัด บรรทัดละ u v w แทนถนนทางเดียวจาก u ไป v
ใช้เวลา w วัน แล้วปิดด้วย k บรรทัด บรรทัดละ t x y แทนเทศกาล
1 ≤ N ≤ 50, N ≤ M ≤ 501,
1 ≤ T ≤ 1,000,000,000, 0 ≤ k ≤ 200,
1 ≤ C[i] ≤ 52,501, 1 ≤ w ≤ 5,
1 ≤ t ≤ T และ 1 ≤ y ≤ 1,000,000,000
เวลา 2 วินาที หน่วยความจำ 512 เมกะไบต์
T พอดีไม่ได้เลย ให้ตอบ -1 N ≤ 5, M ≤ 50 และ T ≤ 5
อีก 20% มี M ≤ 50 และ T ≤ 52,501
อีก 10% มี M ≤ 50 โดยที่ N = M, u[i] = i และ v[i] = (i mod N) + 1
อีก 15% มี M ≤ 50 และ k = 0
อีก 10% มี M ≤ 50 และ k ≤ 10
อีก 10% มี M ≤ 50 เฉย ๆ
และอีก 15% ไม่มีเงื่อนไขเพิ่มเติม
| Input | Output |
|---|---|
| 3 4 11 0 1 3 4 1 2 1 2 1 3 2 3 2 3 1 4 | 13 |
| 4 8 16 3 3 1 2 4 1 2 1 1 3 1 1 3 2 3 4 3 2 3 2 3 2 1 4 2 1 4 1 5 3 3 5 1 2 5 5 4 20 | 39 |
อ่านตัวอย่างนี้ยังไง
ชุดแรกบรรทัดบนสุดอ่านว่ามี 3 เมือง ถนน 4 เส้น แข่งกัน 11 วัน
และไม่มีเทศกาลเลย บรรทัดถัดมาคือความพึงพอใจของเมือง 1 ถึงเมือง 3 เรียงตามลำดับ
คือ 1, 3, 4 ส่วนอีก 4 บรรทัดคือถนน
เลขสามตัวในบรรทัดคือต้นทาง ปลายทาง และจำนวนวัน ระวังว่าถนนเป็นทางเดียว
บรรทัด 2 1 3 แปลว่าไปจากเมือง 2 กลับเมือง 1 ได้ใน 3 วัน แต่ไม่ได้แปลว่าเดินสวนทางได้
คำตอบมีหน่วยเป็นความพึงพอใจรวม ไม่ใช่จำนวนวันและไม่ใช่จำนวนเมืองที่แวะ
และเป็น -1 เมื่อไม่มีทางกลับถึงเมือง 1 ในวันที่ T พอดี
สิ่งที่คนอ่านพลาดบ่อยที่สุดคือนับวันที่ 0 กับวันที่ T ยังไง คำตอบคือนับทั้งสองวัน
เพราะเขาชิมตั้งแต่วันแรกที่ยืนอยู่เมือง 1 และชิมอีกครั้งตอนกลับถึง
แผนที่โจทย์ยกมาคือ 1 → 2 → 1 → 2 → 3 → 1 เดินแล้วได้แบบนี้: วันที่ 0 อยู่เมือง 1 ได้ 1 จากนั้นวันที่ 1 อยู่เมือง 2 ได้ 3 จากนั้นวันที่ 4 อยู่เมือง 1 ได้ 1 จากนั้นวันที่ 5 อยู่เมือง 2 ได้ 3 จากนั้นวันที่ 7 อยู่เมือง 3 ได้ 4 จากนั้นวันที่ 11 อยู่เมือง 1 ได้ 1 รวมทั้งหมด 1 + 3 + 1 + 3 + 4 + 1 เท่ากับ 13 หน่วย สังเกตว่าเขาเหยียบเมือง 1 สามครั้งและได้ 1 หน่วยทุกครั้ง เพราะโจทย์บอกว่าชิมซ้ำก็ได้เท่าเดิม ส่วนชุดที่สองมีเทศกาล 3 งาน จัดวันที่ 3, 1, 5 ตามลำดับที่อินพุตให้มา ซึ่งไม่ได้เรียงตามวัน แผนที่ชนะคือ 1 → 3 → 4 → 2 → 3 → 4 → 1 และมันไปตรงงานเดียวคือวันที่ 5 ที่เมือง 4 ได้เพิ่ม 20 ส่วนอีก 2 งาน เขายอมทิ้งเพราะแวะไม่คุ้ม รวมแล้วได้ 39 หน่วย
ใบ้
ถ้า T เล็ก ข้อนี้คือตารางธรรมดา ช่องหนึ่งช่องคือ “วันที่ d ยืนอยู่เมือง v
แล้วได้มากที่สุดเท่าไร” ไล่จากวันที่ 0 ไปข้างหน้าจนถึงวันที่ T แล้วอ่านคำตอบที่ช่องของเมือง 1
ปัญหาคือ T ใหญ่ได้ถึง 1,000,000,000 ตารางนั้นจึงมีแถวเป็นพันล้านแถว
ทีนี้ลองสังเกตขอบเขตสองตัวที่ดูเล็กจนน่าสงสัย คือเมืองไม่เกิน 50 เมือง และถนนยาวไม่เกิน 5 วัน สองตัวนี้เล็กจนแทบไม่มีเหตุผลอื่นนอกจากผู้ออกโจทย์อยากให้เราเอาไปใช้ ถ้าถนนทุกเส้นยาว 1 วันเท่ากันหมด หนึ่งวันจะเป็นการก้าวแบบเดียวกันเสมอ และของที่ซ้ำเหมือนกันทุกครั้งมักกระโดดข้ามทีละเยอะได้ แล้วถนนที่ยาวไม่เท่ากันล่ะ จะทำให้มันยาวเท่ากันได้ไหม
อาณาจักรเดียวกับตัวอย่างแรก ลองเดินให้กลับถึงเมือง 1 พอดีวันที่ 11 ก่อน แล้วค่อยไล่หายอดที่มากที่สุด
ชุดนี้ไม่มีเทศกาล
ชุดนี้ไม่มีเทศกาล
เทศกาล: วันที่ 5 ที่เมือง 4 ได้เพิ่ม 15
ชุดนี้ไม่มีเทศกาล
กดถนนที่อยากไป วงกลมสีทองคือเมือง 1 ซึ่งเป็นทั้งจุดเริ่มและจุดจบ
ได้ความพึงพอใจทุกครั้งที่เหยียบเมือง รวมวันที่ 0 และวันสุดท้ายด้วย แต่ทริปจะนับก็ต่อเมื่อวันสุดท้ายคุณยืนอยู่ที่เมือง 1 พอดี
ลองให้ครบทั้งสี่ชุดนะครับ โดยเฉพาะชุดสุดท้าย ถ้าลองแล้วรู้สึกว่ามันแปลก ๆ ความรู้สึกนั้นถูกแล้ว
ที่มาของแนวคิดนี้
ผมรู้จักท่ายกกำลังเมทริกซ์อยู่ก่อนแล้ว สิ่งที่ต้องตัดสินใจจริงในข้อนี้จึงไม่ใช่ว่าจะใช้ท่าไหน
แต่คือจะทำยังไงให้ “หนึ่งวัน” เป็นก้าวแบบเดียวกันทุกครั้ง ตัวเลขที่ผลักคือ T ถึง 1,000,000,000
ตารางไล่ทีละวันซึ่งเป็นสิ่งแรกที่ผมเขียน ต้องผ่อนถนนทุกเส้นในทุกวัน คูณออกมาได้ 501,000,000,000 ครั้ง
และตารางเองก็กินหน่วยความจำระดับหลายแสนเมกะไบต์ ไม่ใช่เรื่องปรับจูนให้เร็วขึ้นอีกนิด แต่ต้องเปลี่ยนหน่วยของการคิด
อุปสรรคเดียวที่ขวางอยู่คือถนนยาวไม่เท่ากัน ถ้าทุกเส้นยาว 1 วัน หนึ่งวันก็คือการก้าวหนึ่งครั้งบนกราฟเดิม
ซึ่งยกกำลังได้ทันที พอถนนยาว 1 ถึง 5 วัน วันหนึ่งวันจึงไม่ใช่การก้าวที่เหมือนกันอีกต่อไป
ตัวเลขที่ทำให้กล้าหั่นเมืองเป็นสำเนาคือ w ไม่เกิน 5 กับ N ไม่เกิน 50
คูณกันแล้วได้สถานะแค่ 250 ตัว ซึ่งยกกำลังสามแล้วยังอยู่ในหลักสิบล้าน คือยังไหว
ถ้า w ถึงหลักพันเมื่อไร ท่านี้ตายทันที
สิ่งเดียวที่ผมไม่สบายใจตอนเขียนเสร็จคือรางวัลของเมืองถูกจ่ายตั้งแต่ตอนออกเดินทาง ไม่ใช่ตอนไปถึง ซึ่งอ่านดูเหมือนนับเกิน ผมเลยไม่ยอมตัดสินด้วยเหตุผลในหัวอย่างเดียว แต่เอาไปชนกับตัวไล่ทุกเส้นทาง ที่ไม่รู้จักทั้งการหั่นเมืองและเมทริกซ์ (เหตุผลว่าทำไมมันไม่นับเกิน อยู่ในตอนที่ 4) บทเรียนที่เอาไปใช้ข้ออื่นได้คือ ถ้าอยากกระโดดข้ามเวลาเป็นก้อนใหญ่ ต้องทำให้หนึ่งหน่วยเวลาเป็นก้าวเดียวกันเสมอก่อน แล้ววิธีกระโดดจะตามมาเอง
ท่าคือหั่นเมืองหนึ่งเมืองออกเป็นสำเนา เมืองละ W ตัว เมื่อ W คือความยาวถนนที่มากที่สุด
สำเนาที่ j ของเมือง v เขียนเป็น (v, j) แปลว่า “อีก j วันข้างหน้าฉันจะเหยียบเมือง
v” สำเนา (v, 0) จึงแปลว่ากำลังยืนอยู่ที่เมือง v จริง ๆ ในวันนี้
เมื่อมองแบบนี้ การเดินทางทั้งอาณาจักรเหลือกฎแค่สองข้อ และทั้งสองข้อใช้เวลาหนึ่งวันเท่ากัน
ข้อแรก ถนนจากเมือง u ไปเมือง v ที่ยาว w วัน กลายเป็นการก้าวจาก (u, 0)
ไป (v, w - 1) คือตัดสินใจออกเดินทางวันนี้ แล้วเหลืออีก w - 1 วันจะถึง
ข้อสอง สำเนา (v, j) เมื่อ j มากกว่า 0 ก้าวไป (v, j - 1) ได้อย่างเดียว
คืออยู่ระหว่างทางแล้วเวลาผ่านไปหนึ่งวัน
// สร้างเมทริกซ์ของหนึ่งวัน จากถนนกับโซ่สำเนาเมือง
// id(v, j) = หมายเลขสถานะของสำเนาที่ j ของเมือง v
for (auto [u, v, w] : edges)
A[id(u, 0)][id(v, w - 1)] = max(A[id(u, 0)][id(v, w - 1)], C[v]); // ออกเดินทาง จ่ายรางวัลตรงนี้
for (int v = 0; v < n; v++)
for (int j = 1; j < W; j++)
A[id(v, j)][id(v, j - 1)] = 0; // อยู่ระหว่างทาง ผ่านไปหนึ่งวัน
รางวัล C[v] ถูกบวกที่การก้าวข้อแรก คือตอนออกเดินทาง ไม่ใช่ตอนไปถึง ส่วนการก้าวข้อสองได้ 0
จำนวนสถานะทั้งหมดคือ N คูณ W ซึ่งที่ขอบเขตใหญ่สุดคือ 50 คูณ 5 เท่ากับ 250 ตัว
และตอนนี้หนึ่งวันคือการก้าวหนึ่งครั้งบนกราฟที่มีแค่ 250 จุด เหมือนกันทุกวัน
พอหนึ่งวันเป็นก้าวเดียวกันเสมอ เราเขียนกฎของหนึ่งวันลงเป็นตารางตัวเลขสี่เหลี่ยมที่เรียกว่าเมทริกซ์
(matrix อ่านว่า “เมทริกซ์” คำนี้มาจากภาษาละติน mātrix ที่แปลว่าแม่พันธุ์หรือครรภ์
คือที่ที่อะไรบางอย่างงอกออกมา ก่อนจะถูกยืมมาใช้เรียกตารางตัวเลขในคณิตศาสตร์) ได้ตารางขนาด 250 คูณ 250
ช่องแถว p หลัก q เก็บว่าก้าวจากสถานะ p ไป q ในหนึ่งวันแล้วได้กี่หน่วย
ถ้าก้าวไม่ได้ก็ใส่ค่าลบมหาศาลไว้แทนคำว่าไปไม่ได้
ทีนี้คำถามว่า “เดิน a + b วันแล้วได้มากที่สุดเท่าไร” ตอบได้จากคำตอบของ a วัน
กับ b วัน โดยไล่ดูว่าจุดพักตรงกลางอยู่ที่สถานะไหน แล้วเอาสองท่อนมาบวกกัน เลือกอันที่มากที่สุด
รูปแบบนี้หน้าตาเหมือนการคูณเมทริกซ์เป๊ะ ๆ ต่างกันแค่เปลี่ยนเครื่องหมาย: ที่เดิมต้องบวกให้เปลี่ยนเป็นเอามากสุด
และที่เดิมต้องคูณให้เปลี่ยนเป็นบวก ระบบตัวเลขที่สลับเครื่องหมายแบบนี้เรียกว่าพีชคณิตมากสุดบวก
(max-plus algebra อ่านว่า “แม็กซ์-พลัส” บางตำราเรียกพีชคณิตเขตร้อน เพราะคนที่ศึกษาเรื่องนี้ยุคแรกเป็นชาวบราซิล)
// หนึ่งวันคือการคูณหนึ่งครั้ง แต่บวกกลายเป็นมากสุด และคูณกลายเป็นบวก
// C[i][j] = ค่ามากที่สุดของ A[i][k] + B[k][j] เมื่อไล่ k ทุกตัว
for (int i = 0; i < S; i++)
for (int k = 0; k < S; k++) {
if (A[i][k] <= HALF) continue; // ไปจากสถานะ i ถึง k ไม่ได้ ข้าม
for (int j = 0; j < S; j++)
C[i][j] = max(C[i][j], A[i][k] + B[k][j]);
}
ของดีของการเขียนหนึ่งวันเป็นเมทริกซ์คือมันยกกำลังได้ เมทริกซ์ของ 2 วันคือเมทริกซ์ของ 1 วันคูณตัวเอง
ของ 4 วันคือของ 2 วันคูณตัวเอง ไล่ไปเรื่อย ๆ เก็บไว้เป็นตารางกระโดดสองยกกำลัง ซึ่งเป็นท่าเดียวกับที่
ข้อศูนย์ประชุมใช้กระโดดข้ามงานทีละก้อน ที่ T ถึง 1,000,000,000
เราต้องการกำลังถึง 30 ชั้น คือยกกำลังสองซ้ำ 29 ครั้ง
แต่ละครั้งเป็นการคูณเมทริกซ์ 250 คูณ 250 หนึ่งที ราคา 15,625,000 ครั้ง
ชั้นทั้งหมดกินหน่วยความจำ 15 เมกะไบต์ ซึ่งเทียบกับลิมิต 512 แล้วเหลือเฟือ
พอมีตารางชั้นแล้ว การเดินหน้าไป d วันก็แค่ดูว่า d เขียนเป็นเลขฐานสองแล้วมีบิตไหนติดบ้าง
แล้วเอาเวกเตอร์คำตอบปัจจุบันคูณกับชั้นนั้น ๆ ตามลำดับ ตรงนี้เป็นการคูณเวกเตอร์กับเมทริกซ์
ซึ่งราคาแค่ 62,500 ครั้ง ถูกกว่าการคูณเมทริกซ์เต็ม ๆ อยู่ 250 เท่า
| ทาง | ที่ T = 52,501 | ที่ T = 1,000,000,000 |
|---|---|---|
| ไล่ทีละวัน ทุกวันผ่อนถนนทุกเส้น | 26,303,001 | 501,000,000,000 |
| หั่นเมืองแล้วคูณเมทริกซ์ ยกกำลังทวิภาค | 435,375,000 | 830,000,000 |
ถ้าไม่มีเทศกาลเลย ทั้งข้อจบตรงนี้ คือยกเวกเตอร์เริ่มต้นไป T วันรวดเดียวแล้วอ่านคำตอบ
เทศกาลทำให้ทำแบบนั้นไม่ได้ เพราะรางวัล y ผูกกับวันที่แน่นอนวันเดียว การกระโดดข้ามวันนั้นไปเลย
จะทำให้ไม่มีจังหวะใส่รางวัลเข้าไป
แต่เทศกาลมีไม่เกิน 200 งาน มันจึงหั่นเส้นเวลาออกเป็นช่วงได้ไม่เกิน 201 ช่วงเท่านั้น
วิธีทำคือเรียงเทศกาลตามวัน (อินพุตไม่ได้เรียงมาให้ อย่างตัวอย่างที่สองให้มาเป็นวันที่ 3, 1, 5)
แล้วเดินหน้าทีละช่วงด้วยตารางกระโดด พอถึงวันที่มีงาน ก็เอา y บวกเข้าช่องของสถานะ (x, 0)
ตรง ๆ ซึ่งแปลว่ายืนอยู่เมือง x พอดีวันนั้น แล้วเดินหน้าต่อ
สามอย่างที่ต้องระวังตอนบวก อย่างแรกคือถ้าช่องนั้นยังเป็นค่าลบมหาศาลอยู่ แปลว่าวันนั้นไปยืนที่เมืองนั้นไม่ได้เลย ห้ามบวกเข้าไป ไม่งั้นค่าขยะจะกลายเป็นค่าที่ดูใช้ได้ อย่างที่สองคืองานหลายงานอาจจัดวันเดียวกัน ต้องบวกให้ครบทุกงานก่อนจะเดินหน้าต่อ ถ้าสองงานอยู่เมืองเดียวกันวันเดียวกันก็ทบกันไป ซึ่งถูกแล้วตามโจทย์ อย่างที่สามคือช่วงยาวศูนย์วัน (สองงานติดกันในวันเดียวกัน) ต้องไม่ทำให้โค้ดเดินหน้าผิด
จุดที่ดูน่าสงสัยที่สุดของท่านี้คือ เราบวก C[v] ตอนก้าวจาก (u, 0) ไป (v, w - 1)
ซึ่งคือวันที่เขาออกเดินทาง ไม่ใช่วันที่ไปถึง ถ้า T มาถึงก่อนที่เขาจะเดินทางถึงเมือง v
เท่ากับเราแจกความพึงพอใจของมื้อที่เขายังไม่ได้กินไปแล้ว
เหตุผลที่มันไม่พังอยู่ที่จุดเดียว คือเราอ่านคำตอบจากช่องของสถานะ (1, 0) เท่านั้น
และจากสถานะ (v, j) ที่ j มากกว่า 0 ทางออกมีทางเดียวคือ (v, j - 1)
ไม่มีถนนเส้นไหนออกจากสำเนาที่ยังค้างอยู่ระหว่างทางได้เลย แปลว่าค่าที่ค้างอยู่ในสถานะกลางทางในวันสุดท้าย
ไม่มีทางไหลมาถึงช่อง (1, 0) ได้ มันถูกทิ้งไปพร้อมกับช่องของตัวเอง
พูดอีกแบบคือการยืนอยู่ที่ (1, 0) ในวันที่ T เป็นหลักฐานในตัวมันเองว่า
ทุกการเดินทางที่เคยตัดสินใจไว้ได้ลงจอดครบแล้ว เพราะถ้ามีสักเส้นที่ยังค้าง เขาจะยังติดอยู่ในสำเนา (v, j) บางตัว
ไม่ใช่ที่ (1, 0) การจ่ายล่วงหน้าจึงเป็นแค่เรื่องของจังหวะการบันทึกบัญชี ไม่ใช่การแจกของฟรี
ผมชอบให้ข้ออ้างแบบนี้มีตัวตรวจคอยยืนยัน มากกว่าจะเชื่อเหตุผลที่เขียนไว้เฉย ๆ ตัวไล่ทุกเส้นทางที่ใช้เทียบ
จึงไม่รู้จักทั้งสำเนาเมืองและเมทริกซ์ มันเดินจริงทีละเส้นทาง บวกความพึงพอใจตอนไปถึงจริง ๆ
แล้วเก็บค่ามากที่สุดของเส้นทางที่จบที่เมือง 1 ในวันที่ T พอดี
ถ้าการจ่ายล่วงหน้านับเกินจริง ตัวเลขสองฝั่งจะแยกกันทันทีในเทสเล็ก ๆ ไม่กี่รอบ
คอมไพล์ทั้งสามโปรแกรมแล้วรันกับตัวอย่างสองชุดในโจทย์ ได้ 13 กับ 39 ตรงกันทั้งสามตัว ตัวเฉลยผ่านการสุ่มทดสอบ 57,000 รอบโดยไม่มีรอบไหนไม่ตรง และผมรันซ้ำด้วยเมล็ดสุ่มของตัวเองอีก 6,000 รอบ ก็ไม่ต่างกันสักรอบ ในจำนวนนั้น 3,493 รอบเทียบกับตัวไล่ทุกเส้นทาง นอกจากนี้ยังมีอีก 600 รอบที่เทียบกับสูตรปิด บนอาณาจักรที่บังคับให้เดินได้ทางเดียว โดยดัน T ถึงพันล้านจนได้ใช้บิตกระโดดครบทั้ง 30 บิต อีก 60 รอบที่ขนาดเต็มคือ N = 50, M = 501, k = 200 เทียบกับตารางไล่ทีละวัน และเคสขอบอีกแปดเคสที่คำนวณด้วยมือ เช่น เมืองเดียวที่มีถนนวนกลับตัวเองยาว 1 วันแล้ว T เป็นพันล้าน T คี่กับถนนวนกลับตัวเองยาว 2 วันซึ่งต้องตอบ -1 เทศกาลที่จัดตรงวันที่ T พอดี และเมืองที่ไม่มีถนนออกเลย ทั้งหมดตรงกันหมด เวลาที่แย่ที่สุดที่วัดได้คือ 0.55 วินาที จากลิมิต 2 วินาที บนเคสที่จงใจสร้างให้หนักที่สุด (N = 50, M = 501, T = 1,000,000,000, k = 200 และจัดวันเทศกาลให้ห่างกัน 2 ยกกำลัง 22 ลบหนึ่งวัน เพื่อให้ต้องคูณเวกเตอร์กับเมทริกซ์มากที่สุด) หน่วยความจำสูงสุด 18 เมกะไบต์จาก 512 ทั้งหมดนี้เทียบกับตัวตรวจของเราเองกับตัวอย่างสองชุดในโจทย์ ไม่ใช่ข้อมูลทดสอบจริงของผู้จัด
ท่าแรกคือทำให้หนึ่งหน่วยเวลาเป็นก้าวเดียวกันเสมอ ด้วยการเพิ่มสถานะ เวลาเจอโจทย์ที่เวลาใหญ่มากแต่โครงสร้างเล็ก สิ่งที่ขวางการกระโดดข้ามเวลามักไม่ใช่ขนาด แต่เป็นความไม่สม่ำเสมอ ถนนยาวไม่เท่ากันคือความไม่สม่ำเสมอแบบหนึ่ง และมันซื้อกลับมาได้ด้วยสำเนาของเมืองตามจำนวนวันที่ค้างอยู่ ราคาคือจำนวนสถานะคูณขึ้นตามความยาวมากสุด ซึ่งจ่ายไหวก็ต่อเมื่อความยาวมากสุดเล็ก อย่างข้อนี้ที่ให้มาแค่ 5
ท่าที่สองคือเปลี่ยนเครื่องหมายแล้วใช้ท่าเดิม คำถามหาเส้นทางที่ดีที่สุดในจำนวนก้าวที่กำหนดพอดี
มีหน้าตาเหมือนการคูณเมทริกซ์ทุกประการ ต่างแค่บวกกลายเป็นมากสุดและคูณกลายเป็นบวก
พอมันเป็นการคูณ มันก็ยกกำลังได้ และท่ายกกำลังเร็วที่เคยใช้กับเลขธรรมดาก็ย้ายมาใช้ได้ทั้งดุ้น
(ข้อ ยุบสถานะให้เหลือแถวเดียว ทิ้งท้ายไว้ว่าถ้า n ใหญ่กว่านั้นต้องใช้ท่านี้ ข้อนี้คือท่านั้น)
ท่าที่สามคือเหตุการณ์เฉพาะจุดหั่นเส้นเวลาเป็นช่วง อะไรที่ผูกกับเวลาจุดเดียวและมีจำนวนน้อย ไม่ได้ทำลายท่ากระโดด มันแค่บังคับให้เราหยุดที่จุดนั้นแล้วจัดการด้วยมือ ก่อนจะกระโดดต่อ ค่าใช้จ่ายรวมจึงเป็นจำนวนเหตุการณ์คูณราคาการกระโดดหนึ่งครั้ง
หั่นเมืองเป็นสำเนาตามจำนวนวันที่ยังต้องเดินอีก จนถนนทุกเส้นยาวหนึ่งวันเท่ากัน แล้วหนึ่งวันจะกลายเป็นการคูณเมทริกซ์แบบมากสุดบวกหนึ่งครั้ง ที่เหลือคือยกกำลังข้ามช่วงที่ไม่มีเทศกาล แล้วหยุดใส่รางวัลด้วยมือทีละงาน
ในหน้านี้