418531 ภาคต้น 2552/โจทยปัญหาการค้นหาด้วยพละกำลังเยี่ยงควายถึก/เฉลยข้อ 9

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา

พิจารณาตารางข้างล่างนี้

คะแนนของตารางนี้คือ

เราเห็นได้ว่าคะแนนของตารางแบ่งออกเป็นสองส่วน คือ

  • คะแนนตามแนวนอน: และ
  • คะแนนตามแนวตั้ง:

และนอกจากนี้เรายังสังเกตเพิ่มเติมได้อีกว่า

  • การสลับแถวจะไม่ทำให้คะแนนแนวนอนเปลี่ยน
  • การสลับคอลัมน์จะไม่ทำให้คะแนนแนวตั้งเปลี่ยน

ฉะนั้น เราจึงสามารถแก้ปัญหาในโจทย์ได้โดยการแบ่งอัลกอริทึมออกเป็นสองขั้นตอนดังนี้

  • หาวิธีการสลับคอลัมน์ ให้ได้คะแนนแนวนอนมากที่สุด (โดยไม่ต้องสนใจคะแนนแนวตั้ง)
  • หาวิธีการสลับแถว ให้ได้คะแนนแนวตั้งมากที่สุด (โดยไม่่ต้องสนใจคะแนนแนวนอน)

เมื่อเรานำเอาคะแนนแต่ละแนวที่มากที่สุดมาบวกกัน เราจะได้คะแนนของตารางที่มากที่สุดเท่าที่จะเป็นไปได้

ฉะนั้น ต่อไปนี้เราจะพูดถึงอัลกอริทึมสำหรับหาวิธีการสลับคอลัมน์ให้ได้คะแนนแนวนอนมากที่สุดเท่านั้น อัลกอริทึมสำหรับหาคะแนนแนวตั้งที่มากที่สุดก็มีลักษณะเช่นเดียวกัน

วัตถุ

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

ถ้า แล้ว คอลัมน์ที่ ของตารางที่สลับคอลัมน์แล้ว คือคอลัมน์ที่ ของตารางต้นฉบับ

ค่าของวัตถุ

สมมติให้ตารางต้นฉบับเก็บอยู่ในอะเรย์ เราสามารถเขียนฟังก์ชัน points เพื่อคำนวณคะแนนของตารางที่สลับแล้วได้ดังต่อไปนี้

<geshi lang="c"> points(T, p, n) {

   result = 0
   for i = 1 to n do
       for j = 1 to n-1 do
       {
           d = T[ i, p[j] ] - T[ i, p[j+1] ]
           result = result + d*d
       }
   return result

} </geshi>

เราได้ว่าฟังก์ชัน points ทำงานในเวลา

อัลกอริทึม

เราจะสร้าง permutation ขึ้นมาทีละตัว แล้วสำหรับ permutation แต่ละตัวเราจะเรียกฟังก์ชัน points เพื่อคำนวณคะแนนแนวนอนของตารางหลังจากสลับคอลัมน์ตาม permutation นั้น แล้วจึงนำค่าที่ได้ไปเปรียบเทียบกับค่าที่ต่ำที่สุดที่เคยเจอมา

เนื่องจากมี permutation อยู่ทั้งหมด ตัว และสำหรับแต่ละตัวเราใช้เวลาในการหาค่าของมันเท่ากับ อัลกอริทึมของเราจึงทำงานในเวลา ตามต้องการ