จ่ายรวมปัญหาการเรียกเก็บเงิน


23

มีคนคนที่โต๊ะ ฉันคนวันที่มีการจ่ายเงินหน้าฉันดอลลาร์nipi

บางคนไม่ได้มีค่าใช้จ่ายที่เหมาะสมในการจ่ายตรงเพื่อให้พวกเขาขึ้นมาด้วยวิธีดังต่อไปนี้pi

ก่อนอื่นทุกคนเอาเงินไปวางบนโต๊ะ จากนั้นแต่ละคนจะนำเงินที่ได้ชำระกลับมามากเกินไป

ตั๋วเงินมีชุดราคาคงที่ (ไม่ใช่ส่วนหนึ่งของอินพุต)

ตัวอย่าง: สมมติว่ามีสองคนคืออลิซและบ๊อบ อลิซเป็นหนี้$ 5 และมีห้า$ 1 ค่า บ๊อบเป็นหนี้$ 2 และมีบิลหนึ่งใบ$ 5 หลังจากอลิซกับบ็อบเอาเงินไปวางบนโต๊ะแล้วบ็อบก็จะได้เงินคืน3 ดอลลาร์และทุกคนก็มีความสุข

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

ฉันต้องการค้นหาอัลกอริทึมที่มีคุณสมบัติดังต่อไปนี้:

  1. ข้อมูลป้อนเข้าจะระบุจำนวนคนจำนวนเงินที่แต่ละคนเป็นหนี้และจำนวนเงินของแต่ละสกุลเงินที่แต่ละคนมี

  2. อัลกอริธึมบอกให้แต่ละคนทราบว่าธนบัตรใบใดวางบนโต๊ะในรอบแรก

  3. อัลกอริทึมบอกให้แต่ละคนทราบว่าจะลบรายการใดออกจากตารางในรอบที่สอง

  4. จำนวนตั๋วเงินที่วางไว้บนโต๊ะ + จำนวนตั๋วเงินที่ลบออกจากตารางจะลดลง

หากไม่มีวิธีแก้ปัญหาที่เป็นไปได้อัลกอริทึมก็จะส่งคืนข้อผิดพลาด


9
มีการกำหนดสกุลเงินของตั๋วล่วงหน้าหรือไม่ (พูดกับหน่วยอเมริกา$ 1, $ 2, $ 5, $ 10, $ 20, $ 50, และ$ 100) หรือเป็นส่วนหนึ่งของข้อมูลเข้า? กล่าวอีกนัยหนึ่งอัลกอริทึมต้องจัดการกับความเป็นไปได้ที่หัวหน้าปีศาจมีตั๋วเงินสามใบ$ 7 ตั๋ว$ 13 ตั๋วและตั๋วสิบห้า$ 4หรือไม่
JeffE

1
ตั๋วเงินได้รับการแก้ไข ฉันเดาว่าในกรณีนี้ฉันไม่สามารถลดผลรวมย่อยและพิสูจน์ว่าเป็น NP-Hard ฉันจะแก้ไขมัน
เจ้า Xu Xu

1
คุณต้องมีวิธีในการแสดง 4/5 เป็นการเพิ่มประสิทธิภาพเพียงครั้งเดียว ไม่สามารถปรับให้เหมาะสมสำหรับเงื่อนไขสองประการนี้ ฉันรู้เกี่ยวกับสิ่งที่คุณตั้งใจฉันเคยมีปัญหาที่คล้ายกันมาก่อน แต่คุณต้องหาปริมาณที่แน่นอนว่าการเพิ่มประสิทธิภาพสำหรับเงื่อนไขทั้งสองนั้นหมายถึงอะไร
edA-qa mort-ora-y

3
ฉันคิดว่ามันจะเป็นการดีกว่าถ้าเป็นจุดเริ่มต้นที่จะสมมติว่าทุกคนจ่ายบิลอย่างแน่นอนหรืออัลกอริธึมเพียงรายงานความล้มเหลว
JeffE

2
คำถามที่ตรงนี้คืออะไรมีข้อกำหนดด้านความซับซ้อนหรือไม่ การเขียนอัลกอริธึมไร้เดียงสาดูเหมือนเล็กน้อยหรือฉันขาดอะไรไป?
Stéphane Gimenez

คำตอบ:


6

หากคุณแก้ไขปัญหาด้วยวิธีที่แตกต่างกันเล็กน้อย (แต่เทียบเท่า) อัลกอริทึมจะชัดเจนยิ่งขึ้น:

มี : ฝ่ายที่เกี่ยวข้องn - 1คนและหนึ่ง Restauarant ให้หน้าฉันจะเป็นจำนวนเงินของพรรคเงินที่ฉันควรจะมีหลังจากรับประทานอาหารเสร็จเรียบร้อยแล้วและจ่ายเงิน ตัวอย่างเช่นหากอลิซมีเงิน $ 36 และเป็นหนี้$ 25 บ็อบมี$ 12 และเป็นหนี้$ 11 และคาร์ลมี$ 30 และเป็นหนี้$ 25 เราบอกว่าp 0เป็นร้านอาหารและมี:nn1piip0

p=(61,11,1,5)

นั่นคือเมื่อมื้ออาหารผ่านร้านอาหารควรมี$ 61 อลิซควรมี$ 11 Bob ควรมี$ 1 และ Carl ควรมี$ 5

ตอนนี้ขอการระบุทั้งหมดของม.ค่าใช้จ่ายที่เกี่ยวข้องกับการ ตัวอย่างเช่น:bm

b=(1,5,10,20,1,1,5,5,10,20)

สกุลเงินของธนบัตรไม่สำคัญ แต่ฉันเลือกสกุลเงินดอลลาร์สหรัฐสำหรับตัวอย่างนี้เพราะคุ้นเคย

เรากำลังมองหาเพื่อลดจำนวนของค่าว่ามือเปลี่ยนแปลงเพื่อให้เราเชื่อมโยง "ค่าใช้จ่าย" กับคนที่ออกไปกับการเรียกเก็บเงินJโดยใช้{ 0 , 1 }เมทริกซ์C รายการ 0 ในเมทริกซ์นี้ระบุว่าบิลแต่ละฝ่ายเริ่มต้นด้วย ( C 0 , j = 0สำหรับjทั้งหมดเพราะร้านอาหารเริ่มต้นโดยไม่มีบิล)ij{0,1}CC0,j=0j

ดำเนินการต่อตัวอย่างของเรา:

C=[0000000000000011111111110000111111111100]

บ่งชี้ว่าอลิซเริ่มต้นด้วย$ 1, $ 5, $ 10, $ 20, Bob เริ่มต้นด้วย$ 1, $ 1, $ 5, $ 5, และ Carl เริ่มต้นด้วย$ 10 และ$ 20

อีกครั้งเป้าหมายคือการลดจำนวนตั๋วเงินที่เปลี่ยนมือ ในคำอื่น ๆ :

Minimize:i=0n1j=0m1Ci,jxi,jsubject to:i=0n1xi,j=1 for 0j<m,j=0m1xi,jbj=pi for 0i<n,andxi,j0

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

นี่คือปัญหาการโปรแกรมจำนวนเต็ม 0,1 และเป็นปัญหาสมบูรณ์ (ดู [ Karp 1972 ]) หน้าวิกิพีเดียเกี่ยวกับการเขียนโปรแกรมเชิงเส้นมีข้อมูลเกี่ยวกับอัลกอริทึมที่แตกต่างกันซึ่งสามารถใช้สำหรับปัญหาประเภทนี้

อาจมีทางออกที่ดีที่สุดหลายอย่าง ด้วยมือวิธีแก้ปัญหาแรกสำหรับตัวอย่างที่ฉันพบคือ:

x=[0101100111101000000000001000000000001000]

ซึ่งหมายความว่าอลิซจ่ายอย่างแน่นอน$ 5 และ$ 20 บ๊อบจ่าย$ 1, $ 5 และ$ 5 อย่างแน่นอนและ Carl จ่ายเงินเกิน$ 10 และ$ 20 จากนั้นเอา$ 5 ออกจากตาราง

ฉันยังใช้โมดูลโปรแกรมเชิงเส้นผสมจำนวนเต็มของระบบSage Mathซึ่งมีความสามารถในการใช้แบ็กเอนด์ตัวแก้ปัญหาที่แตกต่างกัน ( GLPK , COIN , CPLEXหรือGurobi ) ทางออกแรกที่ได้คือ

x=[0101010111101000000000001000000000000100]

ซึ่งเกือบจะเหมือนกันยกเว้นว่า Carl เอาค่า "อื่น ๆ " $ 5 ที่ Bob วางไว้บนโต๊ะ

Cx

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

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

O(1)


ว่าปัญหานี้สามารถแสดงเป็น IP ได้ (เกือบ?) ชัดเจน; แต่วิธีนี้ดีแค่ไหน? IP ของแบบฟอร์มที่สร้างขึ้นสามารถแก้ไขได้อย่างมีประสิทธิภาพหรือไม่ ถ้าไม่มีอัลกอริทึมที่เร็วกว่านี้ไหม?
Raphael

มีรูปแบบย่อของ IP นี้โดยมีตัวแปรสำหรับจำนวนตั๋วเงินของสกุลเงินเฉพาะเจาะจงกว่าตัวแปร 0,1 การเปลี่ยนค่าคงที่จะเปลี่ยนความซับซ้อนเล็กน้อยหากจำนวนคนได้รับการแก้ไขเช่นกันอัลกอริทึมของ Lenstra สามารถแก้ไขได้ในเวลาพหุนาม
Chao Xu

-2

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

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