ค่าใช้จ่ายขั้นต่ำในการเชื่อมต่อเกาะทั้งหมดคืออะไร?


84

มีตารางของขนาดN x M เซลล์บางคนเป็นหมู่เกาะที่แสดงโดย '0' และคนอื่น ๆ ที่มีน้ำ เซลล์น้ำแต่ละเซลล์จะมีตัวเลขแสดงถึงต้นทุนของสะพานที่สร้างขึ้นบนเซลล์นั้น คุณต้องหาต้นทุนขั้นต่ำที่เกาะทั้งหมดสามารถเชื่อมต่อได้ เซลล์เชื่อมต่อกับเซลล์อื่นถ้ามันใช้ขอบหรือจุดสุดยอดร่วมกัน

อัลกอริทึมใดที่สามารถใช้แก้ปัญหานี้ได้ สิ่งที่สามารถใช้เป็นแนวทางบังคับเดรัจฉานได้ถ้าค่าของ N, M น้อยมากให้พูดว่า NxM <= 100?

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

http://i.imgur.com/ClcboBy.png

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

รูปภาพ 2


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

@ Asad: ฉันได้เพิ่มรูปภาพเพื่ออธิบายปัญหาในแนวทาง MST
Atul Vaibhav

"เชื่อมต่อทุกๆสองเกาะด้วยสะพานที่สั้นที่สุด" อย่างที่คุณเห็นนั่นเป็นแนวทางที่ไม่ดีอย่างชัดเจน
Karoly Horvath

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

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

คำตอบ:


67

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

  • x_ij : ตัวแปรตัวบ่งชี้ไบนารีว่าเราสร้างสะพานที่ตำแหน่งน้ำ (i, j) หรือไม่
  • y_ijbcn : ตัวบ่งชี้ไบนารีว่าตำแหน่งน้ำ (i, j) เป็นตำแหน่งที่ n ^ th ที่เชื่อมเกาะ b กับเกาะ c
  • l_bc : ตัวแปรตัวบ่งชี้ไบนารีว่าเกาะ b และ c เชื่อมโยงกันโดยตรงหรือไม่ (aka คุณสามารถเดินบนสะพานสี่เหลี่ยมจาก b ถึง c เท่านั้น)

สำหรับค่าใช้จ่ายในการสร้างสะพานc_ij , sum_ij c_ij * x_ijค่าที่มีวัตถุประสงค์เพื่อลดการเป็น เราจำเป็นต้องเพิ่มข้อ จำกัด ต่อไปนี้ให้กับโมเดล:

  • เราจำเป็นต้องแน่ใจว่าตัวแปรy_ijbcnถูกต้อง เราสามารถไปถึงจัตุรัสน้ำได้เสมอถ้าเราสร้างสะพานที่นั่นดังนั้นy_ijbcn <= x_ijสำหรับทุกตำแหน่งน้ำ (i, j) นอกจากนี้y_ijbc1จะต้องเท่ากับ 0 ถ้า (i, j) ไม่มีขอบเกาะ b. สุดท้ายสำหรับ n> 1 y_ijbcnสามารถใช้ได้ก็ต่อเมื่อมีการใช้ตำแหน่งน้ำใกล้เคียงในขั้นตอนที่ n-1 กำหนดN(i, j)ให้เป็นสี่เหลี่ยมน้ำใกล้เคียง (ฉัน j) y_ijbcn <= sum_{(l, m) in N(i, j)} y_lmbc(n-1)นี้จะเทียบเท่ากับ
  • เราจำเป็นต้องตรวจสอบให้แน่ใจว่าตัวแปรl_bcถูกตั้งค่าก็ต่อเมื่อ b และ c เชื่อมโยงกัน ถ้าเรากำหนดให้เป็นสถานที่ที่มีพรมแดนติดเกาะคนี้สามารถทำได้ด้วยI(c)l_bc <= sum_{(i, j) in I(c), n} y_ijbcn
  • เราจำเป็นต้องตรวจสอบให้แน่ใจว่าเกาะทั้งหมดเชื่อมโยงกันไม่ว่าทางตรงหรือทางอ้อม สิ่งนี้สามารถทำได้ด้วยวิธีต่อไปนี้: สำหรับทุกส่วนย่อยที่เหมาะสมของเกาะที่ไม่ว่างเปล่ากำหนดให้มีอย่างน้อยหนึ่งเกาะใน S เชื่อมโยงกับเกาะอย่างน้อยหนึ่งเกาะในส่วนเติมเต็มของ S ซึ่งเราจะเรียกว่า S ' ในข้อ จำกัด ของเราสามารถดำเนินการนี้โดยการเพิ่มข้อ จำกัด สำหรับทุกชุดไม่ว่างเปล่า S ขนาด <= K / 2 (ที่ K sum_{b in S} sum_{c in S'} l_bc >= 1คือจำนวนของเกาะ)

สำหรับตัวอย่างปัญหาที่มีเกาะ K, สี่เหลี่ยมน้ำ W และความยาวเส้นทางสูงสุดที่ระบุ N นี่คือรูปแบบการเขียนโปรแกรมจำนวนเต็มแบบผสมที่มีO(K^2WN)ตัวแปรและO(K^2WN + 2^K)ข้อ จำกัด เห็นได้ชัดว่าสิ่งนี้จะกลายเป็นเรื่องยากเมื่อขนาดของปัญหาใหญ่ขึ้น แต่อาจแก้ไขได้สำหรับขนาดที่คุณสนใจ เพื่อให้เข้าใจถึงความสามารถในการปรับขนาดได้ฉันจะใช้มันใน python โดยใช้แพ็คเกจเยื่อกระดาษ เริ่มต้นด้วยแผนที่ขนาดเล็กกว่า 7 x 9 ที่มีเกาะ 3 เกาะที่ด้านล่างของคำถาม:

import itertools
import pulp
water = {(0, 2): 2.0, (0, 3): 1.0, (0, 4): 1.0, (0, 5): 1.0, (0, 6): 2.0,
         (1, 0): 2.0, (1, 1): 9.0, (1, 2): 1.0, (1, 3): 9.0, (1, 4): 9.0,
         (1, 5): 9.0, (1, 6): 1.0, (1, 7): 9.0, (1, 8): 2.0,
         (2, 0): 1.0, (2, 1): 9.0, (2, 2): 9.0, (2, 3): 1.0, (2, 4): 9.0,
         (2, 5): 1.0, (2, 6): 9.0, (2, 7): 9.0, (2, 8): 1.0,
         (3, 0): 9.0, (3, 1): 1.0, (3, 2): 9.0, (3, 3): 9.0, (3, 4): 5.0,
         (3, 5): 9.0, (3, 6): 9.0, (3, 7): 1.0, (3, 8): 9.0,
         (4, 0): 9.0, (4, 1): 9.0, (4, 2): 1.0, (4, 3): 9.0, (4, 4): 1.0,
         (4, 5): 9.0, (4, 6): 1.0, (4, 7): 9.0, (4, 8): 9.0,
         (5, 0): 9.0, (5, 1): 9.0, (5, 2): 9.0, (5, 3): 2.0, (5, 4): 1.0,
         (5, 5): 2.0, (5, 6): 9.0, (5, 7): 9.0, (5, 8): 9.0,
         (6, 0): 9.0, (6, 1): 9.0, (6, 2): 9.0, (6, 6): 9.0, (6, 7): 9.0,
         (6, 8): 9.0}
islands = {0: [(0, 0), (0, 1)], 1: [(0, 7), (0, 8)], 2: [(6, 3), (6, 4), (6, 5)]}
N = 6

# Island borders
iborders = {}
for k in islands:
    iborders[k] = {}
    for i, j in islands[k]:
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
                if (i+dx, j+dy) in water:
                    iborders[k][(i+dx, j+dy)] = True

# Create models with specified variables
x = pulp.LpVariable.dicts("x", water.keys(), lowBound=0, upBound=1, cat=pulp.LpInteger)
pairs = [(b, c) for b in islands for c in islands if b < c]
yvals = []
for i, j in water:
    for b, c in pairs:
        for n in range(N):
            yvals.append((i, j, b, c, n))

y = pulp.LpVariable.dicts("y", yvals, lowBound=0, upBound=1)
l = pulp.LpVariable.dicts("l", pairs, lowBound=0, upBound=1)
mod = pulp.LpProblem("Islands", pulp.LpMinimize)

# Objective
mod += sum([water[k] * x[k] for k in water])

# Valid y
for k in yvals:
    i, j, b, c, n = k
    mod += y[k] <= x[(i, j)]
    if n == 0 and not (i, j) in iborders[b]:
        mod += y[k] == 0
    elif n > 0:
        mod += y[k] <= sum([y[(i+dx, j+dy, b, c, n-1)] for dx in [-1, 0, 1] for dy in [-1, 0, 1] if (i+dx, j+dy) in water])

# Valid l
for b, c in pairs:
    mod += l[(b, c)] <= sum([y[(i, j, B, C, n)] for i, j, B, C, n in yvals if (i, j) in iborders[c] and B==b and C==c])

# All islands connected (directly or indirectly)
ikeys = islands.keys()
for size in range(1, len(ikeys)/2+1):
    for S in itertools.combinations(ikeys, size):
        thisSubset = {m: True for m in S}
        Sprime = [m for m in ikeys if not m in thisSubset]
        mod += sum([l[(min(b, c), max(b, c))] for b in S for c in Sprime]) >= 1

# Solve and output
mod.solve()
for row in range(min([m[0] for m in water]), max([m[0] for m in water])+1):
    for col in range(min([m[1] for m in water]), max([m[1] for m in water])+1):
        if (row, col) in water:
            if x[(row, col)].value() > 0.999:
                print "B",
            else:
                print "-",
        else:
            print "I",
    print ""

ขั้นตอนนี้ใช้เวลา 1.4 วินาทีในการรันโดยใช้ตัวแก้เริ่มต้นจากแพ็คเกจเยื่อกระดาษ (ตัวแก้ CBC) และผลลัพธ์ที่ถูกต้อง:

I I - - - - - I I 
- - B - - - B - - 
- - - B - B - - - 
- - - - B - - - - 
- - - - B - - - - 
- - - - B - - - - 
- - - I I I - - - 

จากนั้นพิจารณาปัญหาเต็มที่ด้านบนของคำถามซึ่งเป็นตาราง 13 x 14 ที่มีเกาะ 7 เกาะ:

water = {(i, j): 1.0 for i in range(13) for j in range(14)}
islands = {0: [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)],
           1: [(9, 0), (9, 1), (10, 0), (10, 1), (10, 2), (11, 0), (11, 1),
               (11, 2), (12, 0)],
           2: [(0, 7), (0, 8), (1, 7), (1, 8), (2, 7)],
           3: [(7, 7), (8, 6), (8, 7), (8, 8), (9, 7)],
           4: [(0, 11), (0, 12), (0, 13), (1, 12)],
           5: [(4, 10), (4, 11), (5, 10), (5, 11)],
           6: [(11, 8), (11, 9), (11, 13), (12, 8), (12, 9), (12, 10), (12, 11),
               (12, 12), (12, 13)]}
for k in islands:
    for i, j in islands[k]:
        del water[(i, j)]

for i, j in [(10, 7), (10, 8), (10, 9), (10, 10), (10, 11), (10, 12),
             (11, 7), (12, 7)]:
    water[(i, j)] = 20.0

N = 7

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

mod.solve(pulp.solvers.PULP_CBC_CMD(maxSeconds=120))

สิ่งนี้ให้คำตอบที่มีค่าวัตถุประสงค์ 17:

I I - - - - - I I - - I I I 
I I - - - - - I I - - - I - 
I I - - - - - I - B - B - - 
- - B - - - B - - - B - - - 
- - - B - B - - - - I I - - 
- - - - B - - - - - I I - - 
- - - - - B - - - - - B - - 
- - - - - B - I - - - - B - 
- - - - B - I I I - - B - - 
I I - B - - - I - - - - B - 
I I I - - - - - - - - - - B 
I I I - - - - - I I - - - I 
I - - - - - - - I I I I I I 

ในการปรับปรุงคุณภาพของโซลูชันที่คุณได้รับคุณสามารถใช้ตัวแก้ MIP เชิงพาณิชย์ได้ (ฟรีหากคุณอยู่ในสถาบันการศึกษาและอาจจะไม่ฟรี) ตัวอย่างเช่นนี่คือประสิทธิภาพของ Gurobi 6.0.4 อีกครั้งโดยมีเวลา จำกัด 2 นาที (แม้ว่าจากบันทึกการแก้ปัญหาเราอ่านว่าตัวแก้พบโซลูชันที่ดีที่สุดในปัจจุบันภายใน 7 วินาที):

mod.solve(pulp.solvers.GUROBI(timeLimit=120))

สิ่งนี้พบคำตอบของค่าวัตถุประสงค์ 16 ซึ่งดีกว่าที่ OP สามารถหาได้ด้วยมือ!

I I - - - - - I I - - I I I 
I I - - - - - I I - - - I - 
I I - - - - - I - B - B - - 
- - B - - - - - - - B - - - 
- - - B - - - - - - I I - - 
- - - - B - - - - - I I - - 
- - - - - B - - B B - - - - 
- - - - - B - I - - B - - - 
- - - - B - I I I - - B - - 
I I - B - - - I - - - - B - 
I I I - - - - - - - - - - B 
I I I - - - - - I I - - - I 
I - - - - - - - I I I I I I 

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

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

8
นี่คือว่าสิ่งที่ผมกำลังมองหาเมื่อผมเริ่มโปรดปราน ฉันทำให้ฉันประหลาดใจว่าปัญหาที่ไม่สำคัญที่จะอธิบายเช่นนี้สามารถให้เวลาที่ยากลำบากแก่ผู้แก้ปัญหา MIP ได้อย่างไร ฉันสงสัยว่าสิ่งต่อไปนี้เป็นจริงหรือไม่: เส้นทางที่เชื่อมเกาะสองเกาะเป็นเส้นทางที่สั้นที่สุดโดยมีข้อ จำกัด เพิ่มเติมที่ต้องผ่านเซลล์บางเซลล์ (i, j) ตัวอย่างเช่นเกาะด้านซ้ายบนและตรงกลางในสารละลายของ Gurobi เชื่อมโยงกับ SP ที่ถูก จำกัด ให้ผ่านเซลล์ (6, 5) ไม่แน่ใจว่าเป็นความจริงหรือไม่ แต่ในบางจุดก็ดูไม่ดี ขอบคุณสำหรับคำตอบ!
Ioannis

@Ioannis คำถามที่น่าสนใจ - ฉันไม่แน่ใจว่าการคาดเดาของคุณเป็นเรื่องจริงหรือไม่ แต่ดูเหมือนจะเป็นไปได้สำหรับฉัน คุณอาจคิดว่าเซลล์ (i, j) เป็นจุดที่สะพานจากเกาะเหล่านี้ต้องเชื่อมต่อไปยังเกาะอื่น ๆ เพิ่มเติมจากนั้นขึ้นอยู่กับจุดประสานงานนั้นคุณก็แค่ต้องการสร้างสะพานที่ถูกที่สุดเพื่อเชื่อมต่อเกาะ คู่.
josliber

5

วิธีการบังคับแบบเดรัจฉานในรหัสหลอก:

start with a horrible "best" answer
given an nxm map,
    try all 2^(n*m) combinations of bridge/no-bridge for each cell
        if the result is connected, and better than previous best, store it

return best

ใน C ++ สามารถเขียนเป็นไฟล์

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

การเพิ่มประสิทธิภาพ:

  • ด้วยการใช้ "ขีด จำกัด ของสะพาน" และเรียกใช้อัลกอริทึมเพื่อเพิ่มจำนวนสะพานสูงสุดคุณจะพบคำตอบขั้นต่ำได้โดยไม่ต้องสำรวจโครงสร้างทั้งหมด การหาคำตอบแบบ 1 สะพานหากมีอยู่จะเป็น O (nm) แทนที่จะเป็น O (2 ^ nm) - เป็นการปรับปรุงที่ดีมาก
  • คุณสามารถหลีกเลี่ยงการค้นหาได้ (โดยการหยุดการเรียกซ้ำซึ่งเรียกอีกอย่างว่า "การตัดแต่งกิ่ง") เมื่อคุณทำเกินแล้ว bestCostแล้วเพราะไม่มีเหตุผลที่จะคอยดูแลต่อไป ถ้ามันไม่ดีขึ้นอย่าขุดไปเรื่อย ๆ
  • การตัดแต่งกิ่งข้างต้นจะทำงานได้ดีกว่าหากคุณดูผู้สมัครที่ "ดี" ก่อนที่จะมองว่า "ไม่ดี" (ตามที่เป็นอยู่เซลล์ทั้งหมดจะดูจากซ้ายไปขวาจากบนลงล่าง) การฮิวริสติกที่ดีคือการพิจารณาเซลล์ที่อยู่ใกล้กับส่วนประกอบที่ไม่ได้เชื่อมต่อหลายตัวว่ามีลำดับความสำคัญสูงกว่าเซลล์ที่ไม่ได้ อย่างไรก็ตามเมื่อคุณเพิ่มฮิวริสติกการค้นหาของคุณจะเริ่มคล้ายกัน A * (และคุณต้องมีลำดับความสำคัญบางประเภทด้วย)
  • สะพานและสะพานที่ซ้ำกันจนไม่มีที่ใดที่จะหลีกเลี่ยงได้ สะพานใด ๆ ที่ไม่ตัดการเชื่อมต่อเครือข่ายเกาะหากนำออกซ้ำซ้อน

อัลกอริธึมการค้นหาทั่วไปเช่นA *ช่วยให้ค้นหาได้เร็วขึ้นมากแม้ว่าการค้นหาฮิวริสติกส์ที่ดีขึ้นจะไม่ใช่เรื่องง่าย สำหรับแนวทางที่เฉพาะเจาะจงมากขึ้นโดยใช้ผลลัพธ์ที่มีอยู่บนทรีSteinerตามที่แนะนำโดย @Gassa เป็นวิธีที่จะไป แต่โปรดทราบว่าปัญหาของการสร้างต้นไม้ทิบนกริดมุมฉากคือ NP-สมบูรณ์ตามนี้กระดาษโดย Garey และจอห์นสัน

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


"ลองชุดค่าผสม 2 ^ (n * m) ทั้งหมด" เอ่อ2^(13*14) ~ 6.1299822e+54การทำซ้ำ หากเราสมมติว่าคุณสามารถทำซ้ำได้หนึ่งล้านครั้งต่อวินาทีนั่นจะใช้เวลาเพียง ... ~ 194380460000000000000000000000000000000000 "ปี การเพิ่มประสิทธิภาพเหล่านั้นมีความจำเป็นมาก
Mooing Duck

OP ได้ขอ "วิธีการบังคับแบบเดรัจฉานถ้าค่าของ N, M น้อยมากให้พูดว่า NxM <= 100" สมมติว่า 20 บริดจ์ก็เพียงพอแล้วและการเพิ่มประสิทธิภาพเพียงอย่างเดียวที่คุณใช้คือการ จำกัด บริดจ์ด้านบนโซลูชันที่ดีที่สุดจะพบได้ใน O (2 ^ 20) ซึ่งอยู่ในช่วงของคอมพิวเตอร์สมมุติของคุณ
tucuxi

อัลกอริธึมการย้อนรอยหลังส่วนใหญ่ไม่มีประสิทธิภาพอย่างมากจนกว่าคุณจะเพิ่มการตัดแต่งการทำซ้ำลึกและอื่น ๆ นี่ไม่ได้หมายความว่าพวกเขาไม่มีประโยชน์ ตัวอย่างเช่นเครื่องมือหมากรุกมักเอาชนะปรมาจารย์ด้วยอัลกอริทึมเหล่านี้ (ได้รับ - พวกเขาใช้กลอุบายทุกอย่างในหนังสือเพื่อตัด
ทอน

3

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

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


-1

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

น่าเสียดายที่ตอนนี้คุณประสบปัญหาในการแยกเส้นตารางออกไปเพื่อสร้างชุดของโหนดและขอบ ... ปัญหาที่แท้จริงของโพสต์นี้คือ ฉันจะแปลงตาราง nxm ของฉันเป็น {V} และ {E} ได้อย่างไร

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

เมื่อเสร็จแล้วให้เรียกใช้อัลกอริทึมของ Prim และคุณจะได้รับโซลูชันที่ดีที่สุด

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

หากคุณต้องการให้โค้ด (หลอกหรืออย่างอื่น) แปลงตารางของคุณเป็นชุดของ {V} และ {E} โปรดส่งข้อความส่วนตัวมาให้ฉันแล้วฉันจะตรวจสอบการใช้งานร่วมกัน


ค่าน้ำทั้งหมดไม่เท่ากัน (ดูตัวอย่าง) เนื่องจาก Prim ไม่มีแนวคิดในการสร้าง "โหนดเสมือน" เหล่านั้นคุณควรพิจารณาอัลกอริทึมที่ทำ: Steiner trees (โดยที่โหนดเสมือนของคุณเรียกว่า "Steiner points")
tucuxi

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