การแก้เขาวงกตโดยไม่มีความสามารถในการกลับมา


11

ฉันต้องเขียนโปรแกรมที่จะแก้ปัญหาเขาวงกต เขาวงกตมีโครงสร้างกราฟที่แต่ละโหนด - บางห้องและขอบ - ออกจากห้องอื่น:

ป้อนคำอธิบายรูปภาพที่นี่

รายละเอียด:

  • เราเริ่มจากห้องสุ่ม
  • เขาวงกตมีจุดจบตาย, 0 หรือออกไม่กี่
  • เราไม่รู้อะไรเลยเกี่ยวกับเขาวงกตทั้งหมดเพียงจำนวนห้องปัจจุบันและรายชื่อประตูจากมัน
  • เมื่อเราเข้าห้องใหม่เราไม่รู้ว่าเรามาจากไหน (ประตูอะไรจากห้องปัจจุบันทำให้เรากลับไปที่ห้องก่อนหน้า)
  • เราสามารถรับรู้ได้เมื่อเราถึงทางออก
  • แต่ละขั้นตอนเราย้ายจากห้องปัจจุบันไปยังประตูที่มีอยู่
  • ตัวอย่างเช่นถ้าเราอยู่ที่ห้อง 6 เราจะกระโดดข้ามไม่ได้เลย มันเหมือนกับการเคลื่อนไหวของหุ่นยนต์
  • เรารู้ ID ของห้องปัจจุบันอย่างแน่นอน เรารู้ ID ของแต่ละประตูในห้องปัจจุบัน (ไม่ใช่ในเขาวงกตทั้งหมด)
  • เราควบคุมหุ่นยนต์

ฉันดูอัลกอริทึมที่รู้จักทั้งหมด แต่พวกเขาทั้งหมดต้องการความสามารถเพิ่มเติมอย่างน้อยเพื่อกลับไปยังห้องก่อนหน้า ตามข้อกำหนดเราไม่สามารถใช้อัลกอริธึมที่ค้นหาพา ธ ที่สั้นที่สุด (อันที่จริงแล้วฉันไม่ต้องการที่สั้นที่สุด) เพราะเรารู้เพียงเกี่ยวกับห้องปัจจุบันเท่านั้น เราไม่สามารถใช้อัลกอริธึมมือซ้าย - (ขวา -) เนื่องจากไม่ทราบทิศทางของการออก อาจเป็นทางออกเดียวที่ตรงตามข้อกำหนดคือการเลือกทางออกแบบสุ่มในทุกห้องโดยหวังว่าจะพบทางออกเวลา ...

ข้อเสนอแนะวิธีการแก้เขาวงกตในทางที่ชาญฉลาดมากขึ้น?


2
เป็นการบ้านหรือไม่?
MichaelHouse

2
มันเป็นส่วนหนึ่งของการบ้าน (ฉันควรทำเครื่องหมายอย่างใด?) ห้องพักทุกห้องมี ID ที่ไม่ซ้ำกัน
Kyrylo M

2
ห้องมีหมายเลขตามรูปวาดหรือไม่? บางทีมีบางอย่างเกี่ยวกับการย้ายไปสู่ตัวเลขที่สูงกว่า (หรือต่ำกว่าขึ้นอยู่กับว่าคุณเริ่มต้นที่ไหน)
MichaelHouse

2
รายการทางออกอยู่ในลำดับเดียวกันเสมอหรือไม่ เราสามารถสร้างแผนที่ได้หรือไม่ ฉันอยู่ในห้องที่ 5 และฉันไปที่ห้องที่ 2 ในรายการห้องฉันพบห้องที่ 4 ดังนั้นตอนนี้ฉันรู้ว่าห้องที่ 5> 2 (ห้อง 4)
MichaelHouse

4
@archer ในขณะที่การโพสต์ซ้ำอาจช่วยให้คุณได้คำตอบมากขึ้น - ตอนนี้คนอื่นที่ต้องการคำตอบสำหรับคำถามต้องค้นหาไซต์ที่ต่างกันสองไซต์พร้อมชุดคำตอบที่แตกต่างกัน นั่นเป็นเหตุผลที่กฎต้องการคำถามเดียวเพื่อให้คนอื่นได้รับความช่วยเหลือง่ายขึ้น
ไซคลอปส์

คำตอบ:


3

อืมคุณรู้จำนวนห้องจริง ดังนั้นคุณสามารถสร้างโครงสร้างข้อมูล ฉันเดาว่ารายการทางออกไม่มีหมายเลขห้องติดกับมัน แต่หลังจากเลือกสุ่มคุณจะรู้ว่าอย่างน้อยนั่นคือการเชื่อมต่อ

สมมติว่าคุณอยู่ในห้องที่ 4 และเลือกทางออกหนึ่งในสามอย่าง ตอนนี้ระบบจะบอกคุณว่าคุณอยู่ในห้องที่ 6 และเหลือทางออกเดียวเท่านั้น คุณเลือกและกลับมาในห้อง 4 ณ จุดนี้คุณได้รวบรวมข้อมูลบางอย่างเกี่ยวกับโครงสร้างของเขาวงกต ตอนนี้คุณเลือกทางออกอื่นและสิ้นสุดในห้องที่ 5 ข้อมูลโมเอะเกี่ยวกับห้อง 4 (ทางออกหนึ่งถึง 6, ทางออกหนึ่งถึง 5)

คุณสามารถเลือกทางออกที่เฉพาะเจาะจงได้หรือไม่ หมายเลขเหล่านี้พูดว่าถ้าในห้อง 4 ที่คุณเลือกทางออกที่คุณมักจะจบใน 6 มิฉะนั้นคุณอย่างน้อยสามารถค้นหาเส้นทางที่เป็นไปได้

ตกลงอ่านความคิดเห็นของคุณ ดังนั้นหากทางออกมี ID และมีการเชื่อมโยงกับห้องแบบคงที่ (แม้ว่าคุณจะไม่ทราบว่าจะเริ่มต้นที่ใด) คุณเพียงแค่เลือกใหม่และจดจำการเชื่อมต่อทางออก / ห้องและจำทางออกที่พยายามแล้ว ลองออกจากที่ไม่ได้ลองจนกว่าคุณจะค้นหาแต่ละห้องเดี่ยว

ด้วยวิธีนี้มันง่ายจริงๆ หลังจากผ่านไปไม่กี่ขั้นตอนคุณควรมีรายการการเชื่อมต่อที่สมบูรณ์ไม่มากก็น้อย เฉพาะเมื่อคุณเข้าสู่ห้องใหม่คุณสามารถวิ่งสุ่ม (สำหรับสองสามก้าว) แต่ในทุกขั้นตอนคุณจะได้รับข้อมูลเพิ่มเติมและเมื่อใดก็ตามที่คุณเข้าห้องที่เคยเยี่ยมชมมาก่อนคุณสามารถตัดสินใจได้อย่างชาญฉลาด (ไม่ใช่การทดสอบห้องสิ้นสุดที่ 6 อีกครั้งตัวอย่างเช่นเมื่อคุณพบกับ 4 เนื่องจากไม่มีทางออกที่ยังไม่ทดลอง)

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

ไม่แน่ใจ 100% แต่ฉันคิดว่า Peter Norvig เขียนเกี่ยวกับปัญหาที่คล้ายกัน (เขาวงกต Wumpus) ในหนังสือของเขา "ปัญญาประดิษฐ์: วิธีการที่ทันสมัย" แม้ว่าฉันจะจำได้ถูกต้อง แต่มันก็ไม่ได้เกี่ยวกับการค้นพบเส้นทางและการตัดสินใจเกี่ยวกับข้อมูลบางอย่างที่ระบบสามารถรับได้จากห้องข้างเคียง

แก้ไข:

ไม่มันไม่เพียง แต่สุ่ม โดยการติดตามการออกแล้วพยายามทำให้คุณลบความซ้ำซ้อนที่ไม่จำเป็น จริงๆแล้วคุณไม่จำเป็นต้องเลือกแบบสุ่ม

สมมติว่าคุณเริ่มต้นในห้อง 4. ข้อมูลที่คุณได้รับ: 3 ออกจาก A, B, C คุณมักจะเลือกทางออกที่ไม่ได้ใช้ก่อนเสมอ เริ่มต้นด้วย A. คุณสิ้นสุดในห้องที่ 6 ตอนนี้คุณจำได้ว่า 4A => 6 (และใช้แล้ว) ในห้องที่ 6 คุณจะได้รับข้อมูล 1 ทางออก A. คุณเลือกตัวเลือกแรกที่ไม่ได้ใช้ (และในกรณีนี้เท่านั้น) ออกจากห้อง เพราะรู้ว่า 6A => 4 (และไม่มีทางออกใด ๆ ในห้อง 6) ตอนนี้คุณเลือกทางออกถัดไป B และไปยังห้อง 5 ...

ไม่ช้าก็เร็วคุณจะต้องค้นหาห้องทั้งหมดในแบบนั้น แต่ในเรื่องระบบ

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

ตัวอย่างเช่นวิธีนี้คุณสามารถหลีกเลี่ยงการทำงานเป็นวงกลมตลอดเวลาสิ่งที่จะเป็นความเสี่ยงสำหรับวิธีการสุ่มอย่างหมดจด

ในตัวอย่างของเขาวงกตสิ่งนี้น่าจะไม่สำคัญมากนัก แต่ในเขาวงกตขนาดใหญ่ที่มีห้องพักและการเชื่อมต่อจำนวนมากและอาจเป็นห้องที่จัดเรียงเป็นวงกลมระบบนี้รับประกันได้ว่าคุณจะพบทางออกด้วยการทดลองน้อยที่สุดเท่าที่จะทำได้

(ฉันคิดว่าอาจเป็นระบบเดียวกับ Byte56 ที่เกิดขึ้นกับเกม)


ใช่ฉันสามารถเลือกทางออก (ประตู) เฉพาะออกจากห้อง พวกเขามีรหัสที่ไม่ซ้ำกัน ดังนั้นข้อเสนอแนะของคุณคือสำรวจเขาวงกตเต็มก่อนแล้วจึงใช้อัลกอริทึมที่รู้จักกันดี
Kyrylo M

ฉันเริ่มเขียนโปรแกรมและได้รับคำถามใหม่ ... ก่อนอื่นฉันสำรวจห้องทั้งหมดเพื่อสร้างโครงสร้างด้วยการเชื่อมต่อทั้งหมด ขั้นตอนที่สองจะค้นหาเส้นทาง แต่ฉันจะหยุดสร้างเมื่อมีการเพิ่มการเชื่อมต่อทั้งหมด แต่วิธีที่ฉันจะไปถึงทางออกต่อไป ... นี่เป็นเพียงอัลกอริธึมสุ่มเลือก ...
Kyrylo M

10

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

การแทนกราฟ

สามารถจัดเก็บกราฟได้อย่างง่ายดายเป็นคีย์พจนานุกรมค่าที่คีย์คือรหัสห้องและค่าเป็นอาร์เรย์ของห้องที่นำไปสู่

map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}

ส่วนต่อประสานตัวแทน

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

ในกรณีนี้ตัวแทนควรจะสามารถค้นหาสภาพแวดล้อมสำหรับ id ของห้องที่มีอยู่ในมันควรจะสามารถได้รับจำนวนประตูในห้องที่มันอยู่ใน ( หมายเหตุนี่ไม่ใช่ id ของห้อง ประตูนำไปสู่! ) และเขาควรจะสามารถเคลื่อนที่ผ่านประตูได้โดยระบุดัชนีประตู สิ่งอื่นใดที่ตัวแทนต้องรู้ก็คือต้องเข้าใจด้วยตัวเอง

class AgentInterface(object):
    def __init__(self, map, starting_room):
        self.map = map
        self.current_room = starting_room

    def get_door_count(self):
        return len(self.map[self.current_room])

    def go_through_door(self, door):
        result = self.current_room = self.map[self.current_room][door]
        return result

ตัวแทนความรู้

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

คลาสนี้แสดงข้อมูลเกี่ยวกับห้องเดี่ยว ฉันเลือกที่จะจัดเก็บประตูที่ไม่ได้setเข้าชมเป็นประตูเอและที่เข้าเยี่ยมชมเป็นdictionaryที่ที่สำคัญคือรหัสประตูและค่าเป็นรหัสของห้องที่จะนำไปสู่

class RoomKnowledge(object):
    def __init__(self, unvisited_door_count):
        self.unvisited_doors = set(range(unvisited_door_count))
        self.visited_doors = {}

อัลกอริทึมตัวแทน

  • ทุกครั้งที่ตัวแทนเข้ามาในห้องเจ้าหน้าที่จะค้นหาพจนานุกรมความรู้เพื่อหาข้อมูลเกี่ยวกับห้อง หากไม่มีรายการสำหรับห้องนี้ก็จะสร้างขึ้นใหม่RoomKnowledgeและเพิ่มสิ่งนี้ลงในพจนานุกรมความรู้

  • มันจะตรวจสอบว่าห้องปัจจุบันเป็นห้องเป้าหมายหรือไม่ถ้าเป็นเช่นนั้นก็จะส่งคืน

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

  • หากไม่มีประตูที่ไม่ได้เข้าชมเราจะย้อนกลับไปที่ห้องที่เราเคยเยี่ยมชมเพื่อหาประตูที่ไม่ได้เข้าชม

Agentสืบทอดชั้นจากAgentInterfaceชั้น

class Agent(AgentInterface):

    def find_exit(self, exit_room_id):
        knowledge = { }
        room_history = [] # For display purposes only
        history_stack = [] # Used when we need to backtrack if we've visited all the doors in the room
        while True:
            room_knowledge = knowledge.setdefault(self.current_room, RoomKnowledge(self.get_door_count()))
            room_history.append(self.current_room)

            if self.current_room==exit_room_id:
                return room_history

            if len(room_knowledge.unvisited_doors)==0:
                # I have destination room id. I need door id:
                door = find_key(room_knowledge.visited_doors, history_stack.pop())
                self.go_through_door(door)
            else:   
                history_stack.append(self.current_room)
                # Enter the first unopened door:
                opened_door = room_knowledge.unvisited_doors.pop()
                room_knowledge.visited_doors[opened_door]=self.go_through_door(opened_door)

รองรับฟังก์ชั่น

ฉันต้องเขียนฟังก์ชั่นที่จะหากุญแจในพจนานุกรมที่ให้ค่าตั้งแต่เมื่อ backtracking เรารู้ id ของห้องที่เราพยายามไป แต่ไม่ใช่ประตูที่จะไปถึงมัน

def find_key(dictionary, value):
    for key in dictionary:
        if dictionary[key]==value:
            return key

การทดสอบ

ฉันทดสอบชุดตำแหน่งเริ่มต้น / สิ้นสุดทั้งหมดในแผนที่ที่ระบุด้านบน สำหรับชุดค่าผสมแต่ละชุดจะพิมพ์ห้องที่เข้าชม

for start in range(1, 7):
    for exit in range(1, 7):
        print("start room: %d target room: %d"%(start,exit))
        james_bond = Agent(map, start)
        print(james_bond.find_exit(exit))

หมายเหตุ

การย้อนรอยนั้นไม่มีประสิทธิภาพมากในกรณีที่เลวร้ายที่สุดมันสามารถผ่านทุกห้องเพื่อไปยังห้องที่อยู่ติดกันได้ แต่การย้อนรอยนั้นค่อนข้างหายาก - จากการทดสอบข้างต้นจะเป็นการย้อนรอยสามครั้งเท่านั้น ฉันหลีกเลี่ยงการใส่ข้อยกเว้นในการจัดการเพื่อให้รหัสกระชับ ความคิดเห็นใด ๆ เกี่ยวกับ Python ของฉันชื่นชม :)


คำตอบของอนุสาวรีย์! น่าเสียดายที่ไม่สามารถตอบได้สองข้อ :( ฉันได้เขียนโปรแกรมใน C # และโดยทั่วไปแล้วใช้ความคิดแบบเดียวกันเกือบทั้งหมดสำหรับ backtracking ใช้อัลกอริธึมการค้นหาความลึกของลมหายใจ
Kyrylo M

4

โดยพื้นฐานแล้วคุณมีกราฟทิศทางที่ห้องที่เชื่อมต่อทุกห้องเชื่อมต่อกันด้วยข้อความที่ไม่รู้จักสองรายการโดยหนึ่งรายการในทิศทางใดทิศทางหนึ่ง สมมติว่าคุณเริ่มต้นในโหนด1และประตูAและBนำไปสู่ Aคุณไม่ได้รู้ว่าสิ่งที่อยู่ไกลออกไปในแต่ละประตูเพื่อให้คุณเพียงแค่เลือกประตู คุณจะได้รับไปยังห้อง2ที่มีประตูC, และD Eตอนนี้คุณรู้ว่าประตูAนำจากห้อง1ไปที่ห้องแต่คุณไม่ทราบวิธีการที่จะได้รับกลับมาเพื่อให้คุณสุ่มเลือกประตู2 Cคุณกลับไปที่ห้อง1! ตอนนี้คุณรู้วิธีการที่จะได้รับระหว่างห้องพักและ1 2สำรวจต่อไปผ่านประตูที่ไม่รู้จักที่ใกล้ที่สุดจนกว่าคุณจะพบทางออก!


4

เนื่องจากห้องอยู่ในลำดับเดียวกันเสมอในรายการทางออกเราสามารถสร้างแผนที่ห้องพักได้อย่างรวดเร็วในขณะที่กำลังมองหาทางออก

รหัสเทียมของฉันค่อนข้างชวาขอโทษฉันใช้มันบ่อยมาก

Unvisited_Rooms เป็น hashmap ที่ถือ ID ห้องและรายการดัชนีของห้องที่ไม่ได้แมปหรืออาเรย์ 2 มิติไม่ว่าอะไรก็ตาม

ฉันคิดว่าอัลกอริทึมสามารถไปบางอย่างเช่นนี้:

Unvisited_Rooms.add(currentRoom.ID, currentRoom.exits) //add the starting room exits
while(Unvisited_Rooms.Keys.Count > 0 && currentRoom != end) //keep going while there are unmapped exits and we're not at the end
    Room1 = currentRoom
    ExitID = Room1.get_first_unmapped_Room() //returns the index of the first unmapped room
    if(ExitID == -1) //this room didn't have any more unmapped rooms, it's totally mapped
        PathTo(Get_Next_Room_With_Unmapped_Exits) //we need to go to a room with unmapped exits
        continue //we need to start over once we're there, so we don't create false links
    GoToExit(ExitID) //goes to the room, setting current room to the room on the other side
    Room1.Exits[exitID].connection = currentRoom.ID //maps the connection for later path finding
    Unvisited_Rooms[Room1.ID].remove(exitID) //removes the index so we don't worry about it
    if(Unvisited_Rooms[Room1.ID].size < 1) //checks if all the rooms exits have been accounted for
        Unvisited_Rooms.remove(Room1.ID)  //removes the room if it's exits are all mapped
    Unvisited_Rooms.add(currentRoom.ID, currentRoom.unvisited_exits) //adds more exits to the list

If(currentRoom != end && Unvisited_Rooms.Keys.Count < 1)
   print(No exit found!)
else
   print(exit is roomID: currentRoom.ID)

คุณจะต้องใช้หนึ่งในเส้นทางของโหนดที่พบโดยทั่วไปไปยังห้อง PathTo () ใน "แผนที่" หวังว่าจะชัดเจนพอที่จะให้คุณเริ่มต้นกับบางสิ่ง


นี่คือ upvote, @ Byte56 - ซึ่งคิดเป็น 2/3 ของเครื่องหมายถูกที่คุณทำหายไป :)
ไซคลอป

2

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

solved = FALSE

SearchRoom(rooms[0], rooms[0])    // Start at room 1 (or any room)
IF solved THEN
  // solvable
ELSE
  // unsolvable
ENDIF
END

// Recursive function, should run until it searches every room or finds the exit
FUNCTION SearchRoom: curRoom, prevRoom
  // Is this room the 'exit' room
  IF curRoom.IsExit() THEN
    solved = TRUE
    RETURN
  ENDIF

  // Deadend?  (skip starting room)
  IF (curRoom.id <> prevRoom.id) AND (curRoom.doors <= 1) THEN RETURN

  // Search each room the current room leads to
  FOREACH door IN curRoom
    // Skip the room we just came from
    IF door.id <> prevRoom.id THEN
      SearchRoom(door, curRoom)
    ENDIF
    IF solved THEN EXIT LOOP
  NEXT

  RETURN
ENDFUNCTION

[แก้ไข] เพิ่ม 'id' ในการตรวจสอบก่อนหน้าและอัปเดตเพื่อให้วัตถุมีความสำคัญมากขึ้น


1
ฉันไม่รู้ว่าแต่ละขั้นตอนมาจากไหน ดังนั้นอัลกอริทึมนี้จึงไม่สามารถแก้ปัญหาได้ แต่ขอขอบคุณที่ลอง
Kyrylo M

3
ดังนั้นคุณกำลังบอกว่าคุณไม่ได้รับอนุญาตที่จะรู้ว่าห้องก่อนหน้า? หรือว่าคุณไม่รู้จักห้องก่อนหน้า รหัสด้านบนจะติดตามห้องก่อนหน้านี้สำหรับคุณ หากคุณไม่ได้รับอนุญาตให้รู้ฉันไม่คิดว่าจะมีวิธีแก้ปัญหาที่ถูกต้องนอกเหนือจากการวนซ้ำเขาวงกตด้วยจำนวนครั้งที่พยายาม 'x' และถ้าคุณไม่สามารถหาทางออกได้คุณสามารถสันนิษฐานได้ว่าเขาวงกตนั้นแก้ไม่ได้ .
Doug.McFarlane

1
"ฉันไม่รู้" ฉันดูรหัสอีกครั้ง ปัญหาที่สองคือการใช้การเรียกซ้ำเป็นปัญหา ลองจินตนาการว่าคุณอยู่ในเขาวงกต คุณจะใช้อัลกอริทึมแบบเรียกซ้ำเพื่อค้นหาทางออกได้อย่างไร
Kyrylo M

จะเกิดอะไรขึ้นถ้าคุณเริ่มต้นในห้องที่ 6 curRoom.doors <= 1ดังนั้นฟังก์ชั่นจะกลับมาทันทีโดยรู้ว่ามันอยู่ในทางตัน แต่คิดว่ามันได้สำรวจเขาวงกตทั้งหมดแล้ว
dlras2

อยู่ใกล้ แต่มันจะระเบิดสแต็กหากมีกราฟในวงจรที่มีความยาวมากกว่าสอง
โปร่งใส

1

คำตอบสั้น ๆ คือการค้นหาความลึกครั้งแรกด้วยการย้อนรอย คุณสามารถทำสิ่งแรก ๆ ได้อย่างกว้าง ๆ หากคุณต้องการ แต่หุ่นยนต์ตัวน้อยของคุณจะเดินไปมามากขึ้น

เป็นรูปธรรมมากขึ้นสมมติว่าเราได้รับ:

// Moves to the given room, which must have a door between
// it and the current room.
moveTo(room);

// Returns the list of room ids directly reachable from
// the current room.
getDoors();

// Returns true if this room is the exit.
isExit();

ในการหาทางออกเราแค่ต้องการ:

void escape(int startingRoom) {
  Stack<int> path = new Stack<int>();
  path.push(startingRoom);
  escape(path);
}

boolean escape(Stack<int> path) {
  for (int door : getDoors()) {
    // Stop if we've escaped.
    if (isExit()) return true;

    // Don't walk in circles.
    if (path.contains(door)) continue;

    moveTo(door);
    path.push(door);
    if (escape(path)) return true;

    // If we got here, the door didn't lead to an exit. Backtrack.
    path.pop();
    moveTo(path.peek());
  }
}

โทรescape()ด้วย ID ของห้องเริ่มต้นและมันจะย้ายหุ่นยนต์ไปยังทางออก (โดยการโทรmoveTo())


ฉันคิดว่าescape(int startingRoom)ควรจะโทรescape(Stack<int> path)
CiscoIPPhone

1
ฉันคิดว่าif (path.contains(door)) continue;ละเมิดข้อกำหนดของเขา - ตัวแทนไม่รู้จริง ๆ ว่าประตูนำกลับไปที่ห้องที่เขาอยู่แล้วเว้นแต่เขาจะเดินผ่านประตู
CiscoIPPhone

ขอบคุณคงแล้ว! ใช่ตอนนี้ที่ฉันดูข้อกำหนดแล้วปัญหาดูเหมือนว่าจะคาวนิดหน่อย หากคุณไม่สามารถย้อนรอยได้สิ่งที่ดีที่สุดที่คุณหวังคือเดินสุ่ม
เอื้อเฟื้อเผื่อแผ่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.