ไฟ (Fire)

1152

ข้อนี้ให้ตารางขนาด N×NN \times N และต้องการให้เก็บมูลค่ารวมได้มากที่สุดจากตารางนี้โดยทุกการเก็บจะใช้เวลา 1 นาทีและช่องที่ (i,j)(i,j) จะไหม้และเก็บไม่ได้หาก i+j<2+ti+j < 2+t เมื่อ tt คือเวลาในนาที (เช่นช่อง (2,2)(2,2) จะเก็บได้เมื่อ t2t\leq2 กล่าวคือต้องเก็บในนาทีแรกหรือนาทีที่ 2 หากจะเก็บ) ไฟจะไหม้ครบทุกช่องหลังเวลาที่ 2N22N-2

โจทย์ข้อนี้เป็นโจทย์ Greedy กล่าวคือในแต่ละขั้นควรเลือกของที่ดีที่สุด

Greedy Algorithm

เราสามารถพิสูจน์ว่าหากวางแผนการเลือกย้อนจากนาทีสุดท้ายมาถีงนาทีแรก ในแต่ละนาทีหากเลือกของที่มีมูลค่ามากสุดที่ยังไม่ได้วางแผนว่าจะเลือกจะทำให้ได้ผลรวมมากสุด

สังเกตว่าหากนับนาทีย้อนลงมาในแต่ละนาทีที่ลดลงจะมีตัวเลือกมากขึ้นเรื่อยๆ (เพราะมีของที่ยังไม่ไหม้มากขึ้น) และไม่มีตัวเลือกไหนหายไปหากไม่ได้เลือก เช่นในนาทีสุดท้าย t=2N2t=2N -2 จะเหลือเพียงของที่ (N,N)(N,N) ที่เก็บได้และควรเก็บอันนั้น และในนาทีก่อนหน้านั้น t=2N3t=2N -3 ต้องเลือกจาก (N1,N)(N-1,N) และ (N,N1)(N,N-1) และในนาที t=2N4t=2N -4 จะต้องเลือกจาก (N2,N),(N1,N1),(N,N2)(N-2,N), (N-1, N-1), (N, N-2) และอันที่ยังไม่ได้เลือกจาก (N1,N)(N-1,N) กับ (N,N1)(N,N-1)

เราจะพิสูจน์ว่าในเวลาที่ tt สามารถเลือกของที่มูลค่ามากสุดจากอันที่ยังไม่ไหม้และยังไม่ได้วางแผนว่าจะเลือกในเวลาอื่นที่ช้ากว่า tt เพื่อให้ได้ผลรวมสูงสุด ให้ของดังกล่าวเป็นชิ้น XtX_t และให้การเลือกของ Algorithm ที่อธิบายไว้เป็น X1,X2,,X2N2X_1, X_2, \dots, X_{2N-2}

สมมติว่าการเลือกที่ได้ผลรวมมากที่สุดคือ O1,O2,,O2N2O_1, O_2, \dots, O_{2N-2} นั่นคือในเวลา tt จะเลือกของชิ้นที่ OtO_t พิจารณา tt สุดท้ายที่ OtXtO_t \neq X_t มีอยู่สองกรณีคือชิ้น XtX_t ถูกเลือกในเวลา t2<tt_2 < t ซึ่งแปลว่ามี Ot2=XtO_{t_2} = X_t หรือ XtX_t ไม่ถูกเลือกเลย ในกรณีแรกเราสามารถสลับการเลือก Ot2O_{t_2} กับ OtO_t (เพราะทั้งสองจะยังไม่ไหม้ในเวลา t2<tt_2 < t) เพื่อให้ได้ลำดับใหม่ที่มี Ot=XtO_t=X_t ส่วนในกรณีที่สองสามารถสลับ OtO_t มาเป็นการเลือก XtX_t ในเวลา tt แทนเพราะมูลค่าของ XtX_t มีค่าไม่น้อยกว่าค่าอื่นใดๆ ที่ยังไม่ถูกเลือก (เนื่องจาก Ot+1,Ot+2,,O2N2O_{t+1}, O_{t+2}, \dots, O_{2N-2} ตรงกับ Xt+1,Xt+2,,X2N2X_{t+1}, X_{t+2}, \dots, X_{2N-2} ตามที่สมมติไว้)

ดังนั้นแปลว่ามีการเลือกที่ได้ผลรวมมากสุด O1,O2,,O2N2O_1, O_2, \dots, O_{2N-2} โดยที่ Ot=XtO_t = X_t สำหรับทุก tt กล่าวคือการเลือก X1,X2,,X2N2X_1, X_2, \dots, X_{2N-2} เป็นการเลือกที่ได้ผลรวมมากที่สุดแบบหนึ่ง

Solution

เราสามารถ Implement การเลือกค่ามากสุดที่ยังไม่ถูกเลือกด้วย Priority Queue นั่นคือจาก t=2N2t=2N-2 ถึง 11 เราจะ Push ค่าของของชิ้นที่อยู่ที่ (i,j)(i,j) ทุกตัวที่ i+j=t+2i+j = t + 2 เข้าไปใน Priority Queue และ Pop ค่ามากสุดใน Queue ออกมาเป็นตัวที่ถูกเลือกในเวลา tt

Priority Queue จะมีการ Push O(N2)\mathcal{O}(N^2) รอบ (หนึ่งครั้งสำหรับทุกค่าในตาราง) และการ Pop O(N)\mathcal{O}(N) รอบ (หนึ่งครั้งสำหรับทุก tt) การ Push และ Pop ต่างใช้เวลา O(logN2)=O(logN)\mathcal{O}(\log N^2) = \mathcal{O}(\log N) ดังนั้นเวลาทั้งหมดคือ O(N2logN)\mathcal{O}(N^2 \log N) ซึ่งเร็วเพียงพอสำหรับ N=1000N=1000