โจทย์
A* คืออัลกอริทึมหาเส้นทางแบบคลาสสิกในเกมและหุ่นยนต์ มันสำรวจช่องตามลำดับของ f = g + h โดย g คือค่าใช้จ่ายที่จ่ายไปแล้ว และ h คือค่าประมาณแบบฮิวริสติกของค่าใช้จ่ายที่เหลือ
ตารางเก็บค่าใช้จ่ายของแต่ละช่อง: การเข้าไปในช่องหนึ่งเสียค่าเท่ากับค่าของช่องนั้น และ 0 คือกำแพงที่เข้าไปไม่ได้ คุณเริ่มที่ start (ไม่ต้องจ่ายค่าของช่องนี้) และเดินขึ้น ลง ซ้าย หรือขวาได้
ใช้ A* โดยมีระยะทางแมนฮัตตัน |row - goal_row| + |col - goal_col| เป็นฮิวริสติก ทุกช่องที่เดินได้มีค่าอย่างน้อย 1 ฮิวริสติกนี้จึงไม่เคยประมาณเกิน และ A* จะคืนคำตอบที่เหมาะสมที่สุด
จง implement a_star_cost(grid, start, goal)
อินพุต
grid: เมทริกซ์ค่าใช้จ่ายของแต่ละช่อง (0 = กำแพง)
start, goal: ตำแหน่งในรูป [row, col]
เอาต์พุต
คืนค่าใช้จ่ายรวมที่น้อยที่สุดเพื่อไปถึง goal หรือ -1 ถ้าไปไม่ถึง (รวมถึงกรณีที่ start หรือ goal เป็นกำแพง)
เงื่อนไข
1 ≤ จำนวนแถว, จำนวนคอลัมน์ ≤ 100
0 ≤ แต่ละค่าใช้จ่าย ≤ 9
ตัวอย่าง
อินพุต:
goal = [2, 2]
grid = [
[1, 1, 1],
[1, 0, 1],
[1, 1, 1]
]
start = [0, 0]
ผลลัพธ์ที่คาดหวัง:
expected = 4
อินพุต:
std::vector<long long> goal = {2, 2};
std::vector<std::vector<long long>> grid = {
{1, 1, 1},
{1, 0, 1},
{1, 1, 1}
};
std::vector<long long> start = {0, 0};
ผลลัพธ์ที่คาดหวัง:
long long expected = 4;
อินพุต:
long[] goal = new long[] {2, 2};
long[][] grid = new long[][] {
new long[] {1, 1, 1},
new long[] {1, 0, 1},
new long[] {1, 1, 1}
};
long[] start = new long[] {0, 0};
ผลลัพธ์ที่คาดหวัง:
long expected = 4;
คำอธิบาย
ช่องกลางเป็นกำแพง เดินขวาสองครั้งแล้วลงสองครั้ง (หรือลงก่อนแล้วไปขวา) จะเข้าช่องค่า 1 สี่ช่อง รวมเป็น 4
อินพุต:
goal = [0, 2]
grid = [
[1, 9, 1],
[1, 9, 1],
[1, 1, 1]
]
start = [0, 0]
ผลลัพธ์ที่คาดหวัง:
expected = 6
อินพุต:
std::vector<long long> goal = {0, 2};
std::vector<std::vector<long long>> grid = {
{1, 9, 1},
{1, 9, 1},
{1, 1, 1}
};
std::vector<long long> start = {0, 0};
ผลลัพธ์ที่คาดหวัง:
long long expected = 6;
อินพุต:
long[] goal = new long[] {0, 2};
long[][] grid = new long[][] {
new long[] {1, 9, 1},
new long[] {1, 9, 1},
new long[] {1, 1, 1}
};
long[] start = new long[] {0, 0};
ผลลัพธ์ที่คาดหวัง:
long expected = 6;
คำอธิบาย
เดินผ่านช่อง 9 ตรง ๆ เสีย 9 + 1 = 10 แต่ถ้าเดินลง ไปตามแถวล่างสุด แล้วขึ้นกลับมา จะเข้าช่องค่า 1 หกช่อง รวมเป็น 6
แนวทางการแก้
ลองทำเองก่อน แล้วค่อยเปิดคำใบ้ทีละข้อ
คำใบ้ 1
ใช้ priority queue ที่จัดลำดับด้วยต้นทุนที่เดินมาแล้วบวก Manhattan distance ไปยังเป้าหมาย
คำใบ้ 2
เก็บต้นทุนที่ดีที่สุดที่พบสำหรับแต่ละช่อง และขยายช่องนั้นก็ต่อเมื่อเส้นทางนี้ดีกว่าเดิม
คำใบ้ 3
ถือว่า wall และช่องเริ่มหรือเป้าหมายที่ถูกบล็อกเป็นไปไม่ได้ และจำไว้ว่าการเข้าช่องเริ่มต้นไม่มีค่าใช้จ่าย
ความซับซ้อนที่คาดหวัง
เวลา O(rows * cols log(rows * cols)), หน่วยความจำเพิ่ม O(rows * cols)
แหล่งอ้างอิง
โจทย์นี้ปรับให้เหมาะกับ CodeUtility กรุณาทำตามคำชี้แจงและข้อจำกัดด้านบน