กลยุทธ์ที่เหมาะสมที่สุดสำหรับเกมที่เป็นนามธรรม


12

ฉันได้รับปัญหาดังต่อไปนี้ในการให้สัมภาษณ์ (ที่ผมเคยล้มเหลวแล้วจะแก้ปัญหาไม่ได้พยายามที่จะโกงวิธีการที่ผ่านมาของฉัน): เกมเริ่มต้นด้วยจำนวนจำนวนเต็มบวก0 (เช่น0 = 1234 .) หมายเลขนี้จะถูกแปลงเป็นแทน binary และNคือจำนวนบิตที่กำหนดให้1 (เช่นA 0 = b 100 1101 0010 , N = 5 )A0A0=1234N1A0=b100 1101 0010N=5.

ผู้เล่นที่ 1เลือกหมายเลขน้อยกว่า0 B 0ต้องมีเพียงชุดเดียวบิต 1 (เช่นB 0 = 10 0000 0000 = 512 .) ให้1 = 0 - B 0 (เช่นA 1 = 1234 - 512 = 722 = b 10 1101 0010 ) การย้ายจะใช้ได้ถ้าB 0B0A0B0B0=b10 0000 0000=512A1=A0B0A1=1234512=722=b1011010010B0ตอบสนองข้อ จำกัด ก่อนหน้านี้และหากจำนวนบิตที่ตั้งอยู่ใน1ยังคงเท่ากับ NA1

ผู้เล่น 2ดำเนินการต่อจากโดยเลือกB 1 ที่ถูกต้องจากนั้นผู้เล่น 1ดำเนินการต่อจากA 2และอื่น ๆ ผู้เล่นเสียถ้าพวกเขาไม่มีการเคลื่อนไหวที่ถูกต้องเหลืออยู่A1B1A2

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


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

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

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


จากคำอธิบายฉันไม่เข้าใจว่าการเคลื่อนไหวที่เลือกต้องมีการตั้งค่าบิตเดียวเป็น 1 (ฉันคิดว่ามันเป็นเพียงส่วนหนึ่งของตัวอย่าง)
jjmontes

@jjmontes - มันถูกระบุว่าเป็นกฎข้อแรกสำหรับการเลือกหมายเลข B - ตัวอย่างทั้งหมดจะถูกระบุเช่นนี้ทุกอย่างที่อยู่นอกวงเล็บเป็นเรื่องทั่วไป คุณมีข้อเสนอแนะว่ามันชัดเจนกว่านี้หรือไม่?
millimoose

1
B0A0

@Veedrac - ฉันรู้ไหมว่าความพยายามทั้งหมดของฉันทำให้การดำเนินการบิตเร็ตเร็วพอสมควรจะไม่เป็นการสิ้นเปลือง คำตอบอธิบายว่าทำไมมันถึงได้ผลดี
millimoose

@millimoose Bitcount อยู่ในฮาร์ดแวร์สำหรับซีพียูที่ทันสมัยที่สุด!
Veedrac

คำตอบ:


21

011001

1001

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

1

i1101kki

i = 0
k = 0
total = 0
while n > 0:
    if n & 1:
       total += k - i
       i += 1
    n >>= 1
    k += 1

totalO(logn)


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

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

5

วิธีหนึ่งในการแก้ปัญหาดังกล่าวมีดังนี้:

  • ค้นหาวิธีแก้ปัญหาสำหรับค่าง่าย ๆ สองสามอย่างโดยใช้วิธี "memoized brute-force" ที่คุณกำลังแนะนำ

  • เดาคำตอบ (ตำแหน่งไหนชนะและแพ้)

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

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


ใช่ไม่พวกเขาปฏิเสธฉันเพราะสิ่งที่ฉันทำผิดและฉันหมดเวลาแล้ว
millimoose

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

5

หมายเหตุจากคำตอบของ @ orlp ที่เราต้องการความเท่าเทียมกันของผลรวมของการกระจัดจากตำแหน่งเริ่มต้นถึงตำแหน่งสิ้นสุด มาอธิบายเรื่องนี้กัน

       9876543210
       9 76 4  1    (positions at start)
start: 1011010010
end:   0000011111
            43210   (positions at end)

ดังนั้นเราต้องการ

  ((1 - 0) + (4 - 1) + (6 - 2) + (7 - 3) + (9 - 4)) & 1
= ((1 + 4 + 6 + 7 + 9) - (0 + 1 + 2 + 3 + 4)) & 1
= ((1 + 0 + 0 + 1 + 1) - (0 + 1 + 0 + 1 + 0)) & 1

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

= (bitcount(x & ~(UINT_MAX / 0b11)) ^ (0 + 1 + 0 + 1 + 0)) & 1

ส่วนที่สองคือความเท่าเทียมกันของครึ่งxจำนวนบิตใน

= (bitcount(x & ~(UINT_MAX / 0b11)) ^ (bitcount(x) >> 1)) & 1

bitcountสามารถใช้ฮาร์ดแวร์popcntคำแนะนำหรือสามารถดำเนินการได้ด้วยตนเองที่ใช้ว่ามีเพียงอย่างใดอย่างหนึ่งบิตสุดท้ายหรือครั้งที่สองไปสุดท้ายเป็นสิ่งจำเป็นกับการลดลงอย่างรวดเร็วเช่นนี้

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