Mỗi Giáng sinh, chúng tôi vẽ tên cho trao đổi quà tặng trong gia đình mình. Điều này thường liên quan đến mulitple vẽ lại cho đến khi không có ai đã kéo vợ/chồng của họ. Vì vậy, năm nay tôi mã hóa tên của riêng tôi vẽ ứng dụng mà mất trong một loạt các tên, một loạt các cặp đôi không được phép, và gửi một email cho tất cả mọi người với người được tặng của họ đã chọn.Thuật toán santa bí mật
Ngay bây giờ, các thuật toán làm việc như thế này (trong giả):
function DrawNames(list allPeople, map disallowedPairs) returns map
// Make a list of potential candidates
foreach person in allPeople
person.potentialGiftees = People
person.potentialGiftees.Remove(person)
foreach pair in disallowedPairs
if pair.first = person
person.Remove(pair.second)
// Loop through everyone and draw names
while allPeople.count > 0
currentPerson = allPeople.findPersonWithLeastPotentialGiftees
giftee = pickRandomPersonFrom(currentPerson.potentialGiftees)
matches[currentPerson] = giftee
allPeople.Remove(currentPerson)
foreach person in allPeople
person.RemoveIfExists(giftee)
return matches
Có ai người hiểu biết thêm về lý thuyết đồ thị biết một số loại thuật toán mà sẽ làm việc tốt hơn ở đây? Vì mục đích của tôi, công trình này, nhưng tôi tò mò.
CHỈNH SỬA: Vì email đã hết một lúc trước và tôi chỉ hy vọng tìm hiểu điều gì đó tôi sẽ thuật lại câu hỏi này thành câu hỏi lý thuyết đồ thị. Tôi không quá quan tâm đến những trường hợp đặc biệt mà các loại trừ là tất cả các cặp (như vợ chồng không nhận được nhau). Tôi quan tâm nhiều hơn đến những trường hợp có đủ loại trừ để tìm ra giải pháp nào trở thành phần khó khăn. Thuật toán của tôi ở trên chỉ là một thuật toán tham lam đơn giản mà tôi không chắc chắn sẽ thành công trong mọi trường hợp.
Bắt đầu với đồ thị được chỉ dẫn hoàn chỉnh và danh sách các cặp đỉnh. Đối với mỗi cặp đỉnh, loại bỏ cạnh từ đỉnh đầu tiên đến đỉnh thứ hai.
Mục đích là để có được một đồ thị, nơi mỗi đỉnh có một cạnh đến, và một cạnh để lại.
Đó là những gì tôi đang tìm kiếm! Cảm ơn! – Eclipse
Không hoàn toàn: đó là biểu đồ được chỉ dẫn và bạn không nhất thiết muốn có một kết hợp hoàn hảo; bạn chỉ muốn một biểu đồ con sao cho mỗi đỉnh có indegree = outdegree = 1 - a * cycle *. [Có nhiều cách để giảm nó thành một vấn đề phù hợp hoàn hảo, nhưng cũng có nhiều cách để giải quyết nó trực tiếp.] – ShreevatsaR
@ShreevatsaR: Biểu đồ không cần phải được hướng dẫn. Chỉ cần lật một xu để chọn hướng cho mỗi chu kỳ. (Điều này giả định rằng tất cả các cặp danh sách đen là đối xứng.) –