बम छोड़ने वाला एल्गोरिथ्म


212

मेरे पास एक n x mमैट्रिक्स है जिसमें गैर-नकारात्मक पूर्णांक हैं। उदाहरण के लिए:

2 3 4 7 1
1 5 2 6 2
4 3 4 2 1
2 1 2 4 1
3 1 3 4 1
2 1 4 3 2
6 9 1 6 4

"बम गिराना" लक्ष्य सेल की संख्या और उसके सभी आठ पड़ोसियों की संख्या को कम से कम शून्य तक कम कर देता है।

x x x 
x X x
x x x

एक एल्गोरिथ्म क्या है जो सभी कोशिकाओं को शून्य करने के लिए आवश्यक बमों की न्यूनतम संख्या निर्धारित करेगा?

B विकल्प (मेरे सावधान पाठक नहीं होने के कारण)

वास्तव में समस्या का पहला संस्करण वह नहीं है जिसके लिए मैं जवाब मांग रहा हूं। मैंने पूरे कार्य को ध्यान से नहीं पढ़ा, अतिरिक्त अड़चनें हैं, हम कहते हैं:

सरल समस्या के बारे में क्या, जब पंक्ति में अनुक्रम गैर-बढ़ते हुए होना चाहिए:

8 7 6 6 5 संभव इनपुट अनुक्रम है

7 8 5 5 2 7 से नहीं संभव है -> 8 एक क्रम में बढ़ रहा है।

शायद "आसान" मामले के लिए उत्तर खोजने से कठिन के लिए समाधान खोजने में मदद मिलेगी।

पुनश्च: मेरा मानना ​​है कि जब हमारे पास ऊपरी स्थितियों को साफ करने के लिए न्यूनतम बमों की आवश्यकता होती है, तो हम पंक्ति के "बाईं ओर" अधिकांश बमों का उपयोग करते हैं। फिर भी कोई सबूत जो सही हो सकता है?


4
वैसे मुझे ओ.टी. लगता है कि कुछ क्षेत्रों को छोड़ दिया जा सकता है जैसे उदाहरण 2 3 1 5 2,3,1 पर छोड़ना व्यर्थ है, क्योंकि उन पर गिरना कुछ उप-क्षति का कारण बनता है जिसे हम 5. पर छोड़ कर पैदा कर सकते हैं। यह विश्व स्तर पर काम करने का तरीका खोजें (यदि यह सही तरीका है)। समाशोधन 2 में किसी भी पड़ोसी पर गिराए गए 2 बमों के उपयोग की आवश्यकता होती है और 5 अन्य क्षति से युक्त होते हैं। लेकिन फिर मुझे नहीं पता कि बाद में क्या करना है जब आप इसे फिर से लिखते हैं (घटने के बाद), तो आपके पास दो विकल्प होते हैं (नुकसान का एक uber- सेट नहीं है)।
abc

23
क्या यह एनपी किसी भी मौके से कठिन है? यह अधिकतम कवरेज समस्या का एक प्रकार है ।
मिस्टिकियल

14
+1 मुझे सोचने के लिए कुछ दिलचस्प देने के लिए
निक मिचिन्सन

3
@ कोस्टेक, बड़ी समस्या! कृपया लिंक पोस्ट करें।
कर्नल पैनिक

5
शायद आपको स्पष्ट करना चाहिए, आपने कहा सवाल यह है: what's the minimum amount of bombs required to clean the board?क्या इसका मतलब यह है कि वास्तविक बमबारी पैटर्न खोजने के लिए आवश्यक नहीं है, लेकिन बमों की न्यूनतम संख्या क्या है?
रेयान

जवाबों:


38

एक सरल उप-समस्या के लिए इसे कम करने का एक तरीका है।

स्पष्टीकरण के लिए 2 भाग हैं, एल्गोरिथ्म और एल्गोरिथ्म एक इष्टतम समाधान प्रदान करता है। पहले दूसरे के बिना कोई मतलब नहीं होगा, इसलिए मैं क्यों के साथ शुरू करूँगा।

यदि आप आयत पर बमबारी करने की सोचते हैं (एक बड़ी आयत मान लें - कोई किनारे के मामले अभी तक नहीं) तो आप देख सकते हैं कि परिधि पर वर्गों के खोखले आयत को कम करने का एकमात्र तरीका 0 परिधि पर बम लगाना है या खोखले आयत पर बम लगाना है चौकोर परिधि के अंदर। मैं परिधि परत 1 को कॉल करूंगा, और इसके अंदर आयत 2 परत।

एक महत्वपूर्ण अंतर्दृष्टि यह है कि कोई बिंदु बमबारी परत 1 नहीं है, क्योंकि "ब्लास्ट त्रिज्या" जो आपको ऐसा करने से मिलता है वह हमेशा परत 2 से एक और वर्ग के ब्लास्ट त्रिज्या के भीतर निहित होता है। आपको आसानी से खुद को समझाने में सक्षम होना चाहिए।

इसलिए, हम समस्या को कम करने के लिए एक इष्टतम तरीका खोजने के लिए परिधि पर बमबारी कर सकते हैं, फिर हम दोहरा सकते हैं कि जब तक कि सभी वर्ग 0 नहीं हैं।

लेकिन निश्चित रूप से, यह हमेशा एक इष्टतम समाधान नहीं मिलेगा यदि यह परिधि को कम से कम इष्टतम फैशन में बम बनाना संभव है, लेकिन एक्स अतिरिक्त बमों का उपयोग करके आंतरिक परत को> एक्स बमों द्वारा कम करने की समस्या को आसान बनाता है। इसलिए, अगर हम पर्मिटर लेयर को एक कहते हैं, अगर हम लेयर 2 में एक अतिरिक्त एक्स बम लगाते हैं (सिर्फ लेयर 1 के अंदर), तो क्या हम बाद में एक्स से अधिक लेयर 2 की बमबारी के प्रयास को कम कर सकते हैं? दूसरे शब्दों में, हमें यह साबित करना होगा कि बाहरी परिधि को कम करने में हम लालची हो सकते हैं।

लेकिन, हम जानते हैं कि हम लालची हो सकते हैं। क्योंकि लेयर 2 में कोई बम कभी भी लेयर 2 को कम करने में अधिक कुशल नहीं हो सकता है। लेयर में रणनीतिक रूप से रखे गए बम की तुलना में 3. और पहले के समान कारण के लिए - हमेशा एक बम होता है जिसे हम लेयर 3 में रख सकते हैं जो हर वर्ग को प्रभावित करेगा। परत 2 कि एक बम परत 2 में रखा जा सकता है। तो, यह हमें लालची होने के लिए (लालची के इस अर्थ में) कभी भी नुकसान नहीं पहुंचा सकता है।

इसलिए, हमें बस इतना करना है कि अगली आंतरिक परत पर बम लगाकर परमिटर को 0 तक कम करने का इष्टतम तरीका मिल जाए।

पहले कोने में 0 पर बमबारी करने से हम कभी आहत नहीं होते हैं, क्योंकि केवल आंतरिक परत का कोना ही इस तक पहुंच सकता है, इसलिए हमारे पास वास्तव में कोई विकल्प नहीं है (और, परिधि पर कोई भी बम जो कोने तक पहुंच सकता है, उसमें एक ब्लास्ट त्रिज्या है) आंतरिक परत के कोने से ब्लास्ट त्रिज्या)।

एक बार जब हम ऐसा कर लेते हैं, तो 0 कोने से सटे परिधि पर वर्ग केवल आंतरिक भाग से 2 वर्गों तक पहुंच सकते हैं:

0       A       B

C       X       Y

D       Z

इस बिंदु पर परिधि प्रभावी रूप से एक बंद 1 आयामी लूप है, क्योंकि कोई भी बम 3 आसन्न वर्गों को कम करेगा। कोनों के पास कुछ अजीबता को छोड़कर - एक्स ए, बी, सी और डी को "हिट" कर सकता है।

अब हम किसी भी ब्लास्ट त्रिज्या ट्रिक का उपयोग नहीं कर सकते हैं - प्रत्येक वर्ग की स्थिति सममित है, अजीब कोनों को छोड़कर, और यहां तक ​​कि कोई ब्लास्ट त्रिज्या दूसरे का उपसमूह नहीं है। ध्यान दें कि यदि यह एक बंद लूप के बजाय एक पंक्ति (कर्नल पैनिक चर्चा करता है) था तो समाधान तुच्छ है। अंतिम बिंदुओं को घटाकर 0 किया जाना चाहिए, और यह आपको कभी भी अंत बिंदुओं से सटे बिंदुओं पर बमबारी करने के लिए परेशान नहीं करता है, क्योंकि ब्लास्ट त्रिज्या एक सुपरसेट है। एक बार जब आप अपना समापन बिंदु 0 बना लेते हैं, तब भी आपके पास एक नया समापन बिंदु होता है, इसलिए दोहराएं (जब तक कि रेखा सभी 0 न हो)।

इसलिए, यदि हम परत में एकल वर्ग को 0 तक कम कर सकते हैं, तो हमारे पास एक एल्गोरिथ्म है (क्योंकि हमने लूप काट दिया है और अब एंडपॉइंट के साथ एक सीधी रेखा है)। मेरा मानना ​​है कि सबसे कम मूल्य (आप 2 विकल्प दे रहे हैं) के साथ वर्ग से सटे हुए बमिंग, उस न्यूनतम मूल्य के 2 वर्गों के भीतर उच्चतम मूल्य न्यूनतम संभव है (इसे प्रबंधित करने के लिए आपको अपनी बमबारी को विभाजित करना पड़ सकता है) इष्टतम होगा लेकिन मैं (अभी तक?) एक सबूत नहीं है।


+1 - मैं कुछ ऐसा ही लिखने जा रहा था। मुझे लगता है कि आपको मिल गया है!
रेक्स केर

5
@ बीकर, कृपया समस्या को ध्यान से पढ़ें। एक वर्ग पर बमबारी से उसके सभी आठ पड़ोसी कम हो जाते हैं, इसलिए उसकी धारणा वास्तव में सही है।
अंधेरा

20
But, we do know we can be greedy...- मैं इसे नहीं खरीद रहा हूं। 1 1 2 1 1 2परिधि पर विचार करें । बमों की न्यूनतम संख्या 4 है, लेकिन तीन अलग-अलग समाधान हैं। प्रत्येक समाधान का अगली परत पर एक अलग प्रभाव पड़ता है। जब तक एक परिधि के लिए कई न्यूनतम समाधान हैं, तब तक आप आंतरिक परतों पर विचार किए बिना परिधि को पूरी तरह से अलग नहीं कर सकते । मुझे नहीं लगता कि इस समस्या को बिना पीछे किए हल किया जा सकता है।
user1354557 20

4
मैं इस समाधान के बारे में सोच रहा था, लेकिन यह सरल लग रहा था। यह सच है, कि आप लेयर 2 पर बम को साफ करने के लिए लेयर को गिरा सकते हैं, लेयर 1, लेकिन अगर कई सॉल्यूशंस हैं, तो वे उच्च लेयर्स के समाधानों को प्रभावित करते हैं।
लुका रहने

12
@psr: यह काम नहीं करता है। बाहरी परत के लिए इष्टतम बमबारी विधि विश्व स्तर पर इष्टतम नहीं हो सकती है। उदाहरण: 0011100 0100010 0000000 0000000 1110111। पहली परत पर बमबारी करने का इष्टतम तरीका दूसरी पंक्ति के बीच में बम बनाना है, जिससे बाहरी परत को मारने के लिए कुल तीन बम लगते हैं। लेकिन फिर आपको अगली परत की देखभाल के लिए दो बमों की आवश्यकता होती है। इष्टतम को कुल चार बमों की आवश्यकता होती है: पहली दो पंक्तियों के लिए दो और अंतिम पंक्ति के लिए दो।
nnonneo

26

पोलिया कहते हैं, "यदि आप किसी समस्या को हल नहीं कर सकते हैं, तो एक आसान समस्या है जिसे आप हल कर सकते हैं: इसे ढूंढें।"

स्पष्ट सरल समस्या 1-आयामी समस्या है (जब ग्रिड एक एकल पंक्ति है)। आइए सबसे सरल एल्गोरिदम से शुरू करें - सबसे बड़े लक्ष्य पर लालच से बमबारी। यह कब गलत हो जाता है?

यह देखते हुए 1 1 1, लालची एल्गोरिथ्म इस बात के प्रति उदासीन है कि यह किस सेल में पहले बम है। बेशक, केंद्र कोशिका बेहतर है - यह एक बार में सभी तीन कोशिकाओं को शून्य करता है। यह एक नया एल्गोरिदम ए बताता है, "शेष राशि को कम करने के लिए बम"। यह एल्गोरिथ्म कब गलत हो जाता है?

यह देखते हुए 1 1 2 1 1, एल्गोरिथ्म ए 2, 3 या 4 कोशिकाओं पर बमबारी के बीच उदासीन है। लेकिन छोड़ने के लिए 2 सेल पर 0 0 1 1 1बमबारी करना 3 जी सेल को छोड़ने के लिए बमबारी करने से बेहतर है 1 0 1 0 1। उसे कैसे ठीक करें? 3rd सेल में बम होने की समस्या यह है कि यह हमें बाईं ओर काम करता है और दाईं ओर काम करता है जिसे अलग से किया जाना चाहिए।

कैसे के बारे में "बम शेष राशि को कम करने के लिए, लेकिन अधिकतम बाईं ओर (जहां हमने बमबारी की) प्लस न्यूनतम से दाईं ओर अधिकतम करें"। इस एल्गोरिथम को कॉल करें। यह एल्गोरिथ्म कब गलत हो जाता है?


संपादित करें: टिप्पणियों को पढ़ने के बाद, मैं मानता हूं कि एक और अधिक दिलचस्प समस्या एक आयामी समस्या होगी, ताकि छोर जुड़ जाएं। उस पर कोई प्रगति देखना पसंद करेंगे।


40
मुझे यकीन नहीं है कि यह उत्तर इतने सारे अपवित्र क्यों हो रहे हैं - 1 डी का मामला लगभग तुच्छ है, बस हमेशा पहले सकारात्मक तत्व के दाईं ओर बम लगाते हैं। यह काम करता है क्योंकि किसी भी तत्व को बम करने के लिए हमेशा एक इष्टतम तरीका होता है जिसमें केवल 0 इसके बाईं ओर होता है। यह कोने के वर्गों को स्पष्ट रूप से हटाने के लिए 2 डी तक बढ़ाया जा सकता है, लेकिन मुझे इससे परे इसे विस्तारित करने का एक स्पष्ट तरीका नहीं दिखता है ...?
ब्लूराजा - डैनी पफ्लुगुएट

3
@ ब्ल्यूराजा, मैंने अपवित्र किया क्योंकि यह स्पष्ट रूप से चित्रित करता था कि अन्य उत्तरों में चर्चा की गई लालची दृष्टिकोण अपर्याप्त था (कम से कम, इसे एक अतिरिक्त मापदंड के साथ पूरक होने की आवश्यकता थी)। लक्ष्य के कुछ विकल्प, भले ही वे कुल संख्या में समान कमी के परिणामस्वरूप हों, दूसरों की तुलना में अधिक फैली चीजों को छोड़ सकते हैं। मुझे लगता है कि यह 2 डी समस्या के लिए एक उपयोगी अंतर्दृष्टि है।
टिम गुडमैन

3
और सामान्य तौर पर "यदि आप 2 डी मामले पर अटक गए हैं, तो 1 डी मामले को पहले आज़माएं" अच्छी सलाह है।
टिम गुडमैन

21
@ समय: "पहले 1D मामले की कोशिश करो 'अच्छी सलाह है" हाँ यह है, जो इसे एक उत्कृष्ट टिप्पणी करेगा; लेकिन इसका जवाब नहीं है ...
ब्लूराजा - डैनी पफ्लुगुएफ्ट

3
मुझे लगता है कि आपके पास एक अच्छा बिंदु है, हालांकि 1 डी मामला यहां थोड़ा भ्रामक हो सकता है क्योंकि इसका एक सरल समाधान है जो आसानी से उच्च आयामों तक विस्तारित नहीं होता है। मुझे लगता है कि समय-सीमा सीमाओं (मामले के चारों ओर लपेट) के साथ 1 डी मामला बेहतर हो सकता है।
टिम गुडमैन

12

समय से बाहर होने के कारण मुझे केवल एक आंशिक समाधान पर रोकना पड़ा, लेकिन उम्मीद है कि यह आंशिक समाधान भी इस समस्या को हल करने के लिए एक संभावित दृष्टिकोण पर कुछ अंतर्दृष्टि प्रदान करता है।

जब एक कठिन समस्या का सामना करना पड़ता है, तो मुझे समस्या की जगह के बारे में एक अंतर्ज्ञान विकसित करने के लिए सरल समस्याओं के साथ आना पसंद है। यहाँ, मैंने जो पहला कदम उठाया, वह था इस 2-D समस्या को 1-D समस्या में बदलना। एक पंक्ति पर विचार करें:

0 4 2 1 3 0 1

किसी तरह या किसी अन्य, आपको पता है कि आपको 4इसे नीचे लाने के लिए 4 बार या घटनास्थल पर बम की आवश्यकता होगी । चूंकि घटनास्थल के बाईं ओर एक कम संख्या है, इसलिए बमबारी 0या 4ओवर बम विस्फोट करने का कोई लाभ नहीं है 2। वास्तव में, मुझे विश्वास है (लेकिन एक कठोर प्रमाण का अभाव है) 2जब तक कि 4स्पॉट 0 से नीचे नहीं जाता है तब तक बमबारी कम से कम किसी भी अन्य रणनीति के रूप में अच्छी है कि 4नीचे की ओर 0. एक एक रणनीति में दाएं से बाएं बाईं ओर आगे बढ़ सकता है इस तरह:

index = 1
while index < line_length
  while number_at_index(index - 1) > 0
    bomb(index)
  end
  index++
end
# take care of the end of the line
while number_at_index(index - 1) > 0
  bomb(index - 1)
end

एक युगल नमूना बमबारी आदेश:

0 4[2]1 3 0 1
0 3[1]0 3 0 1
0 2[0]0 3 0 1
0 1[0]0 3 0 1
0 0 0 0 3[0]1
0 0 0 0 2[0]0
0 0 0 0 1[0]0
0 0 0 0 0 0 0

4[2]1 3 2 1 5
3[1]0 3 2 1 5
2[0]0 3 2 1 5
1[0]0 3 2 1 5
0 0 0 3[2]1 5
0 0 0 2[1]0 5
0 0 0 1[0]0 5
0 0 0 0 0 0[5]
0 0 0 0 0 0[4]
0 0 0 0 0 0[3]
0 0 0 0 0 0[2]
0 0 0 0 0 0[1]
0 0 0 0 0 0 0

एक संख्या से शुरू करने का विचार जो किसी तरह से नीचे जाने की आवश्यकता है या कोई अन्य अपील है क्योंकि यह अचानक एक समाधान खोजने के लिए प्राप्य हो जाता है कि कुछ के रूप में कम से कम सभी अन्य समाधानों के रूप में अच्छा होने का दावा है ।

जटिलता में अगला कदम जहां कम से कम अच्छा है की यह खोज अभी भी संभव है बोर्ड के किनारे पर है। यह मेरे लिए स्पष्ट है कि बाहरी किनारे पर बम लगाने का कोई सख्त लाभ नहीं है; आप मौके पर बमबारी करने से बेहतर हैं और मुफ्त में तीन अन्य स्थान प्राप्त कर रहे हैं। इसे देखते हुए, हम यह कह सकते हैं कि रिंग को किनारे के अंदर से बम बनाना कम से कम उतना ही अच्छा है जितना कि किनारे पर बम लगाना। इसके अलावा, हम इसे अंतर्ज्ञान के साथ जोड़ सकते हैं कि किनारे के अंदर सही एक पर बमबारी वास्तव में बढ़त रिक्त स्थान को नीचे लाने का एकमात्र तरीका है। 0. और भी अधिक, यह इष्टतम रणनीति का पता लगाने के लिए सामान्य रूप से सरल है (इसमें वह है कम से कम किसी भी अन्य रणनीति के रूप में अच्छा) नीचे कोने की संख्या प्राप्त करने के लिए 0. हम यह सब एक साथ रखते हैं और 2-डी अंतरिक्ष में एक समाधान के बहुत करीब पहुंच सकते हैं।

कोने के टुकड़ों के बारे में अवलोकन को देखते हुए, हम यह सुनिश्चित करने के लिए कह सकते हैं कि हम किसी भी शुरुआती बोर्ड से सभी कोनों पर शून्य वाले बोर्ड से जाने की इष्टतम रणनीति जानते हैं। यह इस तरह के बोर्ड का एक उदाहरण है (मैंने ऊपर दो रैखिक बोर्डों से संख्या उधार ली है)। मैंने कुछ स्थानों को अलग तरह से लेबल किया है, और मैं बताऊंगा कि क्यों।

0 4 2 1 3 0 1 0
4 x x x x x x 4
2 y y y y y y 2
1 y y y y y y 1
3 y y y y y y 3
2 y y y y y y 2
1 y y y y y y 1
5 y y y y y y 5
0 4 2 1 3 0 1 0

एक शीर्ष पंक्ति पर ध्यान देगा जो वास्तव में हम पहले देखे गए रैखिक उदाहरण के समान है। हमारे पहले के अवलोकन को याद करते हुए कि शीर्ष पंक्ति को 0 से नीचे लाने का इष्टतम तरीका दूसरी पंक्ति ( xपंक्ति) को बम बनाना है । किसी भी पंक्ति पर बम लगाकर शीर्ष पंक्ति को साफ करने का कोई तरीका नहीं है yऔर पंक्ति पर संबंधित स्थान पर बमबारी करने के लिए शीर्ष पंक्ति पर बमबारी करने का कोई अतिरिक्त लाभ नहीं है x

हम ऊपर से रैखिक रणनीति ( पंक्ति पर संबंधित रिक्त स्थान पर बमबारी ) लागू कर सकते हैंx , केवल शीर्ष पंक्ति के साथ खुद के बारे में और कुछ नहीं। यह कुछ इस तरह होगा:

0 4 2 1 3 0 1 0
4 x[x]x x x x 4
2 y y y y y y 2
1 y y y y y y 1
3 y y y y y y 3
2 y y y y y y 2
1 y y y y y y 1
5 y y y y y y 5
0 4 2 1 3 0 1 0

0 3 1 0 3 0 1 0
4 x[x]x x x x 4
2 y y y y y y 2
1 y y y y y y 1
3 y y y y y y 3
2 y y y y y y 2
1 y y y y y y 1
5 y y y y y y 5
0 4 2 1 3 0 1 0

0 2 0 0 3 0 1 0
4 x[x]x x x x 4
2 y y y y y y 2
1 y y y y y y 1
3 y y y y y y 3
2 y y y y y y 2
1 y y y y y y 1
5 y y y y y y 5
0 4 2 1 3 0 1 0

0 1 0 0 3 0 1 0
4 x[x]x x x x 4
2 y y y y y y 2
1 y y y y y y 1
3 y y y y y y 3
2 y y y y y y 2
1 y y y y y y 1
5 y y y y y y 5
0 4 2 1 3 0 1 0

0 0 0 0 3 0 1 0
4 x x x x x x 4
2 y y y y y y 2
1 y y y y y y 1
3 y y y y y y 3
2 y y y y y y 2
1 y y y y y y 1
5 y y y y y y 5
0 4 2 1 3 0 1 0

अंतिम दो बम विस्फोटों में इस दृष्टिकोण का दोष बहुत स्पष्ट हो जाता है। यह स्पष्ट है, यह देखते हुए कि 4दूसरी पंक्ति में पहले कॉलम में केवल कम करने वाली एकमात्र बम साइटें पहली xऔर एक हैं y। अंतिम दो बम धमाके स्पष्ट रूप से केवल पहले बमबारी करने के लिए हीन हैं x, जिसने ठीक ऐसा ही किया होगा (शीर्ष पंक्ति में पहले स्थान के संबंध में, जिसके पास हमारे पास समाशोधन का कोई अन्य तरीका नहीं है)। चूंकि हमने प्रदर्शित किया है कि हमारी वर्तमान रणनीति उप-रूपीय है, इसलिए रणनीति में संशोधन की स्पष्ट रूप से आवश्यकता है।

इस बिंदु पर, मैं जटिलता में एक कदम पीछे हट सकता हूं और सिर्फ एक कोने पर ध्यान केंद्रित कर सकता हूं। आइए इस पर विचार करें:

0 4 2 1
4 x y a
2 z . .
1 b . .

4शून्य के साथ रिक्त स्थान प्राप्त करने का एकमात्र तरीका स्पष्ट है , और, और x, के कुछ संयोजन को बम बनाना है । मेरे मन में कुछ कलाबाजी के साथ, मैं काफी हूँ यकीन है कि इष्टतम समाधान बम से उड़ाने की है तीन बार और फिर उसके बाद । अब यह पता लगाने की बात है कि मैं उस समाधान तक कैसे पहुंचा और अगर यह किसी भी अंतर्ज्ञान को प्रकट करता है तो हम इस स्थानीय समस्या को हल करने के लिए भी उपयोग कर सकते हैं। मुझे लगता है कि वहाँ और रिक्त स्थान की कोई बमबारी नहीं है । उन स्थानों पर बम लगाने का प्रयास किया जा रहा है, जहां से ऐसा लगता है कि इस तरह से दिखने वाला एक कोना है:yzxabyz

0 4 2 5 0
4 x y a .
2 z . . .
5 b . . .
0 . . . .

इस एक के लिए, यह मेरे लिए स्पष्ट है कि इष्टतम समाधान y5 बार और z5 बार बम है। एक कदम आगे बढ़ते हैं।

0 4 2 5 6 0 0
4 x y a . . .
2 z . . . . .
5 b . . . . .
6 . . . . . .
0 . . . . . .
0 . . . . . .

यहां, यह समान रूप से सहज महसूस करता है कि इष्टतम समाधान बम aऔर b6 बार और फिर x4 बार है।

अब यह उन अंतर्ज्ञानों को सिद्धांतों में बदलने का एक खेल बन जाता है जिन्हें हम बना सकते हैं।

उम्मीद है कि जारी रखा जाएगा!


10

अद्यतन प्रश्न के लिए एक सरल लालची एल्गोरिथ्म इष्टतम परिणाम देता है।

सेल ए [1,1] में ए [0,0] बम गिराएं, फिर सेल ए [2,1] में ए [1,0] बम गिराएं, और इस प्रक्रिया को नीचे की ओर जारी रखें। नीचे के बाएं कोने को साफ करने के लिए, सेल A [N-2,1] पर अधिकतम (A [N-1,0], A [N-2,0], A [N-3,0] बम गिराएं। यह पहले 3 कॉलम को पूरी तरह से साफ कर देगा।

उसी दृष्टिकोण के साथ साफ कॉलम 3,4,5, फिर कॉलम 6,7,8, आदि।

दुर्भाग्य से यह मूल समस्या का समाधान खोजने में मदद नहीं करता है।


"बड़ी" समस्या ("गैर-बढ़ती" बाधा के बिना) एनपी-हार्ड साबित हो सकती है। यहाँ एक सबूत के स्केच है।

मान लीजिए, हमारे पास 3. डिग्री तक का एक प्लैनर ग्राफ है। आइए इस ग्राफ के लिए न्यूनतम वर्टेक्स कवर खोजें । विकिपीडिया लेख के अनुसार यह समस्या 3. डिग्री तक के प्लानर ग्राफ के लिए NP-hard है। यह Planar 3SAT से घटाकर साबित किया जा सकता है। और प्लानर 3SAT की कठोरता - 3SAT से कमी करके। इन दोनों साक्ष्यों को प्रोफेसर द्वारा "अल्गोरिथमिक लोअर बाउंड्स" में हाल के व्याख्यान में प्रस्तुत किया गया है । एरिक डेमिनेक (व्याख्यान 7 और 9)।

यदि हम मूल ग्राफ के कुछ किनारों को विभाजित करते हैं (आरेख पर बाएं ग्राफ), तो प्रत्येक में अतिरिक्त नोड्स की संख्या भी होती है, जिसके परिणामस्वरूप ग्राफ (आरेख पर दाएं ग्राफ) मूल कोने के लिए बिल्कुल न्यूनतम वर्टेक्स कवर होना चाहिए। इस तरह के परिवर्तन ग्रिड पर मनमाना पदों के लिए ग्राफ कोने संरेखित करने की अनुमति देता है।

यहां छवि विवरण दर्ज करें

यदि हम ग्राफ़ को केवल पंक्तियों और स्तंभों के लिए जोड़ते हैं (इस तरह से कि एक किनारे पर कोई दो किनारों की घटना एक तीव्र कोण नहीं बनती है), "एज" को कहीं भी एक किनारे डालें, और "ग्रिड" को अन्य ग्रिड स्थितियों में डालें, हम मूल समस्या के लिए न्यूनतम शीर्ष कवर खोजने के लिए किसी भी समाधान का उपयोग कर सकते हैं।


बाएं से वह ग्राफ कहां से आता है? क्षमा करें, मैं आपके स्पष्टीकरण को काफी नहीं समझता हूँ!
रयिस्त

1
@ryyst: बाईं ओर का ग्राफ़ केवल एक प्लैनर ग्राफ का एक उदाहरण है। इसका उपयोग ग्रिड-संरेखित ग्राफ और फिर n * m मैट्रिक्स तक डिग्री के किसी भी प्लानर ग्राफ को 4 में बदलने के तरीके को प्रदर्शित करने के लिए किया जाता है। इस मैट्रिक्स पर लागू "बम ड्रॉपिंग" एल्गोरिथ्म इस रूपांतरित ग्राफ के लिए शीर्ष आवरण समस्या को हल करेगा और इसलिए "बाएं" ग्राफ़ के लिए।
एवगेनी क्लुव

आह, मैं इसे अभी प्राप्त करता हूं, और मुझे विश्वास है कि आपका परिवर्तन सही है। धन्यवाद!
ryyst

@EvgenyKluev, मुझे लगता है कि अब आपको यह साबित करने की जरूरत है कि वर्टेक्स कवर अभी भी एनपी-हार्ड है "4 के लिए डिग्री के प्लैनर ग्राफ" के लिए।
शहबाज

@ शहबाज: मुझे डर है कि यह सबूत बहुत लंबा हो जाएगा। इसलिए मैंने सबूत के लिए लिंक जोड़ा।
इविवि क्लूव

9

आप इस समस्या का पूर्णांक प्रोग्रामिंग समस्या के रूप में प्रतिनिधित्व कर सकते हैं । (यह इस समस्या से निपटने के संभावित समाधानों में से एक है)

अंक होने:

a b c d
e f g h
i j k l
m n o p

उदाहरण के लिए बिंदु f के लिए 16 समीकरण लिख सकते हैं

f <= ai + bi + ci + ei + fi + gi + ii + ji + ki   

सभी अनुक्रमित और पूर्णांक समाधान के योग पर न्यूनतम।

समाधान निश्चित रूप से इस सूचकांक का योग है।

यह सभी xi को सीमाओं 0 पर सेट करके और सरल बनाया जा सकता है, इसलिए आप इस उदाहरण में 4 + 1 समीकरण रखते हैं।

समस्या यह है कि इस तरह की समस्याओं को हल करने के लिए कोई तुच्छ नहीं है। tI इस पर विशेषज्ञ नहीं है, लेकिन रैखिक प्रोग्रामिंग के रूप में इस समस्या को हल करना एनपी कठिन है।


8
एनपी में सभी समस्याओं को पूर्णांक प्रोग्रामिंग समस्याओं के रूप में तैयार किया जा सकता है, इसलिए यह बहुत उपयोगी नहीं है, जब तक कि हम पहले से ही यह नहीं जानते कि समस्या एनपी-पूर्ण है
ब्लूराजा - डैनी पफ्लुगुफ्ट

1
मैं सहमत हूँ। यह जानना भी आवश्यक नहीं है कि सटीक चाल क्या है, यह जानने के लिए कि क्या समाधान है।
लुका रहाने

1
जब आप सीमा को 0 पर सेट करते हैं, तो असमानताओं की संख्या अभी भी 16 होती है।
Darksky

9

यह एक आंशिक उत्तर है, मैं एक निचली सीमा और ऊपरी सीमा को खोजने की कोशिश कर रहा हूं जो बम की संभावित संख्या हो सकती है।

3x3 और छोटे बोर्ड में, समाधान तुच्छ रूप से हमेशा सबसे बड़ी संख्या वाला सेल होता है।

4x4 से बड़े बोर्डों में, पहला स्पष्ट निचला भाग कोनों का योग होता है:

*2* 3  7 *1*
 1  5  6  2
 2  1  3  2
*6* 9  6 *4*

हालाँकि आप बम की व्यवस्था करते हैं, यह 4x4 बोर्ड को 2 + 1 + 6 + 4 = 13 बम से कम के साथ साफ़ करना असंभव है।

अन्य उत्तरों में यह उल्लेख किया गया है कि कोने को खत्म करने के लिए बम को दूसरे कोने पर रखना बम को कोने पर रखने से भी बदतर नहीं है, इसलिए बोर्ड दिया गया है:

*2* 3  4  7 *1*
 1  5  2  6  2
 4  3  4  2  1
 2  1  2  4  1
 3  1  3  4  1
 2  1  4  3  2
*6* 9  1  6 *4*

हम एक नया बोर्ड देने के लिए दूसरे कोने पर बम रखकर कोनों को शून्य कर सकते हैं:

 0  1  1  6  0
 0  3  0  5  1
 2  1  1  1  0
 2  1  2  4  1
 0  0  0  0  0
 0  0  0  0  0
 0  3  0  2  0

अब तक सब ठीक है। कोनों को साफ करने के लिए हमें 13 बम चाहिए।

अब नीचे दी गई संख्या 6, 4, 3 और 2 को देखें:

 0  1  1 *6* 0
 0  3  0  5  1
 2  1  1  1  0
*2* 1  2 *4* 1
 0  0  0  0  0
 0  0  0  0  0
 0 *3* 0  2  0

एकल बम का उपयोग करने वाले उन दो सेल में से किसी पर बम लगाने का कोई तरीका नहीं है , इसलिए न्यूनतम बम में 6 + 4 + 3 + 2 की वृद्धि हुई है, इसलिए हम कोनों को साफ करने के लिए उपयोग किए जाने वाले बमों की संख्या में जोड़ते हैं, हमें यह मिलता है कि न्यूनतम इस नक्शे के लिए आवश्यक बमों की संख्या 28 बम हो गई है। 28 से कम बमों वाले इस नक्शे को साफ करना असंभव है, यह इस नक्शे के लिए कम बाध्य है।

आप एक ऊपरी बाध्यता स्थापित करने के लिए लालची एल्गोरिथ्म का उपयोग कर सकते हैं। अन्य उत्तरों से पता चला है कि एक लालची एल्गोरिथ्म एक समाधान पैदा करता है जो 28 बमों का उपयोग करता है। चूंकि हम पहले साबित कर चुके हैं कि कोई भी इष्टतम समाधान 28 से कम बम नहीं हो सकता है, इसलिए 28 बम वास्तव में एक इष्टतम समाधान है।

जब लालची और मेरे द्वारा बताए गए न्यूनतम बाउंड को खोजने का तरीका नहीं होता है, हालांकि, मुझे लगता है कि आपको इन संयोजनों की जांच करने के लिए वापस जाना होगा।

निम्न सीमा को खोजने के लिए एल्गोरिथ्म निम्नलिखित है:

  1. उच्चतम संख्या वाला एक तत्व चुनें, इसे P नाम दें।
  2. पी और पी से दो कदम दूर सभी कोशिकाओं को चिन्हित करें।
  3. minimumsसूची में P जोड़ें ।
  4. चरण 1 तक दोहराएं जब तक कि सभी कोशिकाएं अप्रभावी न हों।
  5. minimumsनिचली सीमा प्राप्त करने के लिए सूची में योग करें ।

9

यह एक लालची दृष्टिकोण होगा:

  1. ऑर्डर n X m के "स्कोर" मैट्रिक्स की गणना करें, जहां स्कोर [i] [j] मैट्रिक्स में अंकों की कुल कटौती है यदि स्थिति (i, j) पर बमबारी की जाती है। (एक बिंदु का अधिकतम स्कोर 9 है और न्यूनतम स्कोर 0 है)

  2. पंक्तिबद्ध वार, उच्चतम स्कोर के साथ पहली स्थिति ढूंढें और चुनें (कहते हैं (i, j))।

  3. बम (i, j)। बम गिनती बढ़ाएँ।

  4. यदि मूल मैट्रिक्स के सभी तत्व शून्य नहीं हैं, तो गोटो 1।

मुझे मेरा संदेह है कि यह इष्टतम समाधान है।

संपादित करें:

लालची दृष्टिकोण मैंने ऊपर पोस्ट किया है, जबकि यह काम करता है, सबसे शायद हमें इष्टतम समाधान नहीं देता है। इसलिए मुझे लगा कि डीपी के कुछ तत्वों को इसमें मिला देना चाहिए।

मुझे लगता है कि हम इस बात से सहमत हो सकते हैं कि किसी भी समय, उच्चतम "स्कोर" (स्कोर [i] [j] = अंकों की कुल कटौती अगर (i, j) पर बमबारी हुई है) को लक्षित किया जाना चाहिए। इस धारणा के साथ, यहाँ नया दृष्टिकोण है:

NumOfBombs (M): (आवश्यक बम विस्फोटों की न्यूनतम संख्या लौटाता है)

  1. आदेश n X m के एक मैट्रिक्स M को देखते हुए। यदि M के सभी तत्व शून्य हैं, तो 0 वापस करें।

  2. "स्कोर" मैट्रिक्स एम की गणना करें।

    K को अलग-अलग स्थिति P1, P2, ... Pk (1 <= k <= n * m) बताएं, उच्चतम स्कोर वाले पदों में M हों।

  3. वापसी (1 + मिनट (NumOfBombs (M1), NumOfBombs (M2), ..., NumOfBombs (Mk)))

    जहां M1, M2, ..., Mk परिणामी मेट्रिस हैं यदि हम क्रमशः P1, P2, ..., Pk को बम बनाते हैं।

इसके अलावा, अगर हम इसके अलावा nuke के पदों का क्रम चाहते हैं, तो हमें "मिनट" के परिणामों पर नज़र रखनी होगी।


3
मुझे आश्चर्य है कि यदि वर्तमान मूल्यों का योग बनाने के लिए स्कोर स्थापित करना बेहतर परिणाम देगा। यह अनिवार्य रूप से जमीन को अधिक कुशलता से समतल करेगा।
यूजीन

@ यूजीन: बहुत दिलचस्प बिंदु। मैं एक कारण नहीं सोच सकता कि आपका रास्ता बेहतर परिणाम क्यों नहीं पैदा कर सकता ...
18

@ यूजीन: शायद आसपास के मौजूदा मूल्यों का योग "प्राथमिकता" उपाय के लिए इस्तेमाल किया जा सकता है? उच्चतम स्कोर और सर्वोच्च प्राथमिकता के साथ नोड को
पीछे छोड़ दें

बस इस उत्तर को पढ़ें, मुझे लगता है कि यह मेरे द्वारा पोस्ट किए गए दूसरे उत्तर के समान है (शायद मेरे उत्तर में कुछ और लिखा गया है)। मुझे लगता है कि यह इष्टतम होगा यदि हमेशा अधिकतम स्कोर के साथ एक ही स्थान था, क्योंकि आपको गारंटी दी जाएगी कि हर बम विस्फोट का सबसे बड़ा प्रभाव संभव है। बम विस्फोट का क्रम कोई मायने नहीं रखता है, इसलिए प्रत्येक चरण पर सबसे अच्छे के साथ जाना इष्टतम होना चाहिए। लेकिन क्योंकि "सर्वश्रेष्ठ" के लिए संबंध हो सकते हैं, हो सकता है कि एक इष्टतम समाधान के लिए आपको एक ट्रैक होने पर दोनों को वापस ट्रैक करने और प्रयास करने की आवश्यकता हो।
टिम गुडमैन

1
@ यूजीन, शायद मैं आपका पीछा नहीं कर रहा हूं। सबसे बड़ी कमी और सभी शेष मूल्यों के सबसे छोटे योग के बीच अंतर क्या है? शेष मानों (बमबारी के बाद) का योग उस स्थान को बमबारी से कम करने का वर्तमान कुल मूल्य है, इसलिए ये समान नहीं हैं?
टिम गुडमैन

8

आपकी नई समस्या, पंक्तियों में नॉनकॉन्डिंग मूल्यों के साथ, हल करना काफी आसान है।

निरीक्षण करें कि बाएं स्तंभ में सबसे अधिक संख्याएँ हैं। इसलिए, किसी भी इष्टतम समाधान को पहले इस कॉलम को शून्य तक कम करना होगा। इस प्रकार, हम इस कॉलम के ऊपर एक 1-डी बॉम्बिंग रन कर सकते हैं , जिससे हर तत्व शून्य हो जाएगा। हमने बमों को दूसरे कॉलम पर गिरने दिया ताकि वे अधिकतम नुकसान कर सकें। 1 डी मामले से निपटने के लिए यहां कई पोस्ट हैं, मुझे लगता है, इसलिए मैं उस मामले को छोड़ देने में सुरक्षित महसूस करता हूं। (यदि आप चाहते हैं कि मैं इसका वर्णन करूं, तो मैं कर सकता हूं।) घटती संपत्ति के कारण, तीन सबसे बाएं स्तंभ सभी शून्य हो जाएंगे। लेकिन, हम यहां बमों की एक न्यूनतम संख्या का उपयोग करेंगे, क्योंकि बाएं स्तंभ को शून्य होना चाहिए।

अब, एक बार बायाँ स्तंभ शून्य हो जाने के बाद, हम अभी तीन बचे हुए स्तंभों को ट्रिम करते हैं जो अब शून्य हो गए हैं और अब-कम किए गए मैट्रिक्स के साथ दोहराते हैं। यह हमें एक इष्टतम समाधान प्रदान करना चाहिए क्योंकि प्रत्येक चरण में हम बमों की एक न्यूनतम संख्या का उपयोग करते हैं।


मैं समझ गया। मैंने भी ऐसा ही सोचा था। : एस अगली बार मैं और अधिक ध्यान से पढ़ूंगा। लेकिन इसके लिए धन्यवाद कि कई लोगों को हल करने के लिए 'अच्छी' समस्या है।
abc

4

Mathematica Integer Linear प्रोग्रामिंग ब्रांच-एंड-बाउंड का उपयोग करते हुए

जैसा कि पहले ही उल्लेख किया गया है, पूर्णांक रैखिक प्रोग्रामिंग (जो एनपी-हार्ड है ) का उपयोग करके इस समस्या को हल किया जा सकता है । Mathematica में पहले से ही ILP बना हुआ है। "To solve an integer linear programming problem Mathematica first solves the equational constraints, reducing the problem to one containing inequality constraints only. Then it uses lattice reduction techniques to put the inequality system in a simpler form. Finally, it solves the simplified optimization problem using a branch-and-bound method."[ Mathematica में विवश अनुकूलन ट्यूटोरियल देखें ]]

मैंने निम्नलिखित कोड लिखा है जो गणितज्ञ के आईएलपी पुस्तकालयों का उपयोग करता है। यह आश्चर्यजनक रूप से तेज है।

solveMatrixBombProblem[problem_, r_, c_] := 
 Module[{}, 
  bombEffect[x_, y_, m_, n_] := 
   Table[If[(i == x || i == x - 1 || i == x + 1) && (j == y || 
        j == y - 1 || j == y + 1), 1, 0], {i, 1, m}, {j, 1, n}];
  bombMatrix[m_, n_] := 
   Transpose[
    Table[Table[
      Part[bombEffect[(i - Mod[i, n])/n + 1, Mod[i, n] + 1, m, 
        n], (j - Mod[j, n])/n + 1, Mod[j, n] + 1], {j, 0, 
       m*n - 1}], {i, 0, m*n - 1}]];
  X := x /@ Range[c*r];
  sol = Minimize[{Total[X], 
     And @@ Thread[bombMatrix[r, c].X >= problem] && 
      And @@ Thread[X >= 0] && Total[X] <= 10^100 && 
      Element[X, Integers]}, X];
  Print["Minimum required bombs = ", sol[[1]]];
  Print["A possible solution = ", 
   MatrixForm[
    Table[x[c*i + j + 1] /. sol[[2]], {i, 0, r - 1}, {j, 0, 
      c - 1}]]];]

समस्या में दिए गए उदाहरण के लिए:

solveMatrixBombProblem[{2, 3, 4, 7, 1, 1, 5, 2, 6, 2, 4, 3, 4, 2, 1, 2, 1, 2, 4, 1, 3, 1, 3, 4, 1, 2, 1, 4, 3, 2, 6, 9, 1, 6, 4}, 7, 5]

आउटपुट

यहां छवि विवरण दर्ज करें

लालची एल्गोरिथ्म के साथ इसे पढ़ने वाले किसी के लिए भी

निम्नलिखित 10x10 समस्या पर अपना कोड आज़माएं:

5   20  7   1   9   8   19  16  11  3  
17  8   15  17  12  4   5   16  8   18  
4   19  12  11  9   7   4   15  14  6  
17  20  4   9   19  8   17  2   10  8  
3   9   10  13  8   9   12  12  6   18  
16  16  2   10  7   12  17  11  4   15  
11  1   15  1   5   11  3   12  8   3  
7   11  16  19  17  11  20  2   5   19  
5   18  2   17  7   14  19  11  1   6  
13  20  8   4   15  10  19  5   11  12

यहाँ यह अल्पविराम से अलग है:

5, 20, 7, 1, 9, 8, 19, 16, 11, 3, 17, 8, 15, 17, 12, 4, 5, 16, 8, 18, 4, 19, 12, 11, 9, 7, 4, 15, 14, 6, 17, 20, 4, 9, 19, 8, 17, 2, 10, 8, 3, 9, 10, 13, 8, 9, 12, 12, 6, 18, 16, 16, 2, 10, 7, 12, 17, 11, 4, 15, 11, 1, 15, 1, 5, 11, 3, 12, 8, 3, 7, 11, 16, 19, 17, 11, 20, 2, 5, 19, 5, 18, 2, 17, 7, 14, 19, 11, 1, 6, 13, 20, 8, 4, 15, 10, 19, 5, 11, 12

इस समस्या के लिए, मेरे समाधान में 208 बम हैं। यहां एक संभावित समाधान है (मैं लगभग 12 सेकंड में इसे हल करने में सक्षम था)।

यहां छवि विवरण दर्ज करें

मैथेमेटिका के परिणामों का परीक्षण करने के तरीके के रूप में, देखें कि क्या आपका लालची एल्गोरिथ्म किसी भी बेहतर कर सकता है।


मैं इस उत्तर के साथ 219 में करने में सक्षम था: stackoverflow.com/questions/15300149/bomb-dropping-algorithm/…
एंथनी क्वीन

3

समस्या को रैखिक उप-समस्याओं में बदलने की आवश्यकता नहीं है।

इसके बजाय एक साधारण लालची अनुमानी का उपयोग करें, जो सबसे बड़े से शुरू होकर, कोनों पर बम लगाना है

दिए गए उदाहरण में चार कोने हैं, {2, 1, 6, 4}। प्रत्येक कोने के लिए कोने में सेल विकर्ण को बम से बेहतर चाल नहीं है, इसलिए हम एक तथ्य के लिए जानते हैं कि हमारे पहले 2 + 1 + 6 + 4 = 13 बम इन विकर्ण कोशिकाओं में होने चाहिए। बमबारी करने के बाद हमें एक नए मैट्रिक्स के साथ छोड़ दिया जाता है:

2 3 4 7 1      0 1 1 6 0      0 1 1 6 0     1 1 6 0     0 0 5     0 0 0 
1 5 2 6 2      0 3 0 5 1      0 3 0 5 1  => 1 0 4 0  => 0 0 3  => 0 0 0  
4 3 4 2 1      2 1 1 1 0      2 1 1 1 0     0 0 0 0     0 0 0     0 0 3  
2 1 2 4 1  =>  2 1 2 4 1  =>  2 1 2 4 1     0 0 3 0     0 0 3      
3 1 3 4 1      0 0 0 0 0      0 0 0 0 0 
2 1 4 3 2      0 0 0 0 0      0 0 0 0 0 
6 9 1 6 4      0 3 0 2 0      0 0 0 0 0 

पहले 13 बम विस्फोटों के बाद हम तीन बमों के माध्यम से 3 0 2 को समाप्त करने के लिए विधर्मी का उपयोग करते हैं। अब, हमारे पास 4 पंक्ति में 2 नए कोने, {2, 1} हैं। हम उन बमों, एक और 3 बम विस्फोट। हमने अब मैट्रिक्स को 4 x 4 तक घटा दिया है। एक कोना है, ऊपरी बाएँ। हम उस बम। अब हमारे पास 2 कोने बचे हैं, {5, 3}। चूंकि 5 सबसे बड़ा कोना है, जो पहले बम, 5 बम और फिर दूसरे कोने में 3 पर बम गिराता है। कुल 13 + 3 + 3 + 1 + 5 + 3 = 28 है।


1
मुझे समझ नहीं आ रहा है कि कोनों को बम से
उड़ाने के

कोने पर बमबारी करना कभी भी कोने से अंदर की ओर बमबारी करने से अधिक प्रभावी नहीं है।
psr

1
psr आप मेरी पोस्ट को गलत समझते हैं, मैं AM कोने से तिरछे बमबारी कर रहा हूं, पोस्ट को फिर से पोस्ट करता हूं
Tyler Durden

11
@TylerDurden: यह केवल इसलिए काम करता है क्योंकि मैट्रिक्स छोटा है। बड़े मैट्रिस पर, कोने पर बम लगाने के बाद, आप आमतौर पर किनारों को काट नहीं पाएंगे।
रेयान

3

यह पदों की इस "भूलभुलैया" के माध्यम से सबसे छोटे पथ (बमों की एक श्रृंखला) के लिए एक चौड़ाई खोज करता है। नहीं, मैं यह साबित नहीं कर सकता कि कोई तेज़ एल्गोरिथम नहीं है, क्षमा करें।

#!/usr/bin/env python

M = ((1,2,3,4),
     (2,3,4,5),
     (5,2,7,4),
     (2,3,5,8))

def eachPossibleMove(m):
  for y in range(1, len(m)-1):
    for x in range(1, len(m[0])-1):
      if (0 == m[y-1][x-1] == m[y-1][x] == m[y-1][x+1] ==
               m[y][x-1]   == m[y][x]   == m[y][x+1] ==
               m[y+1][x-1] == m[y+1][x] == m[y+1][x+1]):
        continue
      yield x, y

def bomb(m, (mx, my)):
  return tuple(tuple(max(0, m[y][x]-1)
      if mx-1 <= x <= mx+1 and my-1 <= y <= my+1
      else m[y][x]
      for x in range(len(m[y])))
    for y in range(len(m)))

def findFirstSolution(m, path=[]):
#  print path
#  print m
  if sum(map(sum, m)) == 0:  # empty?
    return path
  for move in eachPossibleMove(m):
    return findFirstSolution(bomb(m, move), path + [ move ])

def findShortestSolution(m):
  black = {}
  nextWhite = { m: [] }
  while nextWhite:
    white = nextWhite
    nextWhite = {}
    for position, path in white.iteritems():
      for move in eachPossibleMove(position):
        nextPosition = bomb(position, move)
        nextPath = path + [ move ]
        if sum(map(sum, nextPosition)) == 0:  # empty?
          return nextPath
        if nextPosition in black or nextPosition in white:
          continue  # ignore, found that one before
        nextWhite[nextPosition] = nextPath

def main(argv):
  if argv[1] == 'first':
    print findFirstSolution(M)
  elif argv[1] == 'shortest':
    print findShortestSolution(M)
  else:
    raise NotImplementedError(argv[1])

if __name__ == '__main__':
  import sys
  sys.exit(main(sys.argv))

1
इस एल्गोरिथ्म जाएगा चाल और उनमें कम लगता है, लेकिन यह एक बहुत लंबे समय लग सकता है। क्या आपने इसे दिए गए डेटा सेट पर चलाया है? यह अन्य एल्गोरिदम के खिलाफ तुलना करने के लिए एक आधार रेखा देगा।
रयान अमोस

1
दिए गए मैट्रिक्स के 5x4 का एक सबसेट लगभग 2 सेकंड में हल हो गया, 5x5 पहले से ही 2 मिनट से अधिक समय लगा। मैंने अभी तक अधिक प्रयास नहीं किया ;-) हाँ, यह एल्गोरिथम किसी भी चीज़ के लिए अनुकूलित नहीं है, लेकिन मूल कार्य: सबसे छोटा समाधान ढूंढें।
अल्फ

2
यह घातीय जटिलता की सुंदरता है।
रयान अमोस

3

ऐसा लगता है कि एक रैखिक प्रोग्रामिंग दृष्टिकोण यहाँ बहुत मददगार हो सकता है।

बता दें कि P m xn पदों के मूल्यों के साथ मैट्रिक्स है:

पदों का मैट्रिक्स

अब एक बम मैट्रिक्स B (x, y) mxn को परिभाषित करें , 1 ≤ x , m , 1 as y ≤ n नीचे के रूप में

बम मैट्रिक्स

इस तरह से कि

बम मैट्रिक्स में पदों का मान

उदाहरण के लिए:

बी (3, 3)

इसलिए हम एक मैट्रिक्स B m xn = [ b ij ] को देख रहे हैं

  1. बम मैट्रिसेस के योग के रूप में परिभाषित किया जा सकता है:

    B बम मैट्रिसेस के योग के रूप में

    ( q ij तब बम की मात्रा होगी जो हम स्थिति p ij में छोड़ देंगे )

  2. p ij - b ij ( 0 (अधिक रसीद होने के लिए, हम इसे P - B ≤ 0 कहते हैं )

इसके अलावा, बी को राशि को कम करना चाहिए बमों की मात्रा का योग

हम B को बदसूरत मैट्रिक्स के रूप में भी आगे लिख सकते हैं :

बी मात्रा के एक मैट्रिक्स के रूप में

और जब से P - B ( 0 (जिसका अर्थ है P we B ) हमारे पास निम्न लीनियर असमानता प्रणाली है:

बम गिराए जाने और पदों में मूल्यों के बीच संबंध

होने के नाते क्ष एम.एन. एक्स 1 के रूप में परिभाषित

राशियों का वेक्टर

p mn x 1 के रूप में परिभाषित किया गया है

P का मान वेक्टर के रूप में वितरित किया जाता है

हम कह सकते हैं कि हम एक प्रणाली है प्रणाली के मैट्रिक्स http://latex.codecogs.com/gif.download?S%5Cmathbf%7Bq%7D&space;%5Cge&space;%5Cmathbf%7Bp%7D उत्पाद के रूप में प्रतिनिधित्व नीचे जा रहा है एस एम.एन. एक्स mn मैट्रिक्स प्रणाली को हल करने के उलट किया जाना है। मैंने खुद इसका विस्तार नहीं किया लेकिन मेरा मानना ​​है कि इसे कोड में करना आसान होना चाहिए।

अब, हमारे पास एक न्यूनतम समस्या है जिसे कहा जा सकता है

जिस सिस्टम को हमें हल करना है

मेरा मानना ​​है कि यह कुछ आसान है, लगभग तुच्छ है जिसे सिम्पलेक्स एल्गोरिथ्म की तरह कुछ हल किया जा सकता है (इसके बारे में यह अच्छा डॉक्टर है )। हालांकि, मुझे पता है कि लगभग कोई रेखीय प्रोग्रामिंग नहीं है (मैं कौरसेरा पर इसके बारे में एक कोर्स करूंगा लेकिन यह अभी भविष्य में है ...), मेरे पास कुछ सिरदर्द थे जो इसे समझने की कोशिश कर रहे थे और मुझे खत्म करने के लिए एक बहुत बड़ा फ्रीलांस काम है बस यहाँ छोड़ दो। यह हो सकता है कि मैंने कुछ बिंदु पर कुछ गलत किया, या कि यह किसी भी आगे नहीं बढ़ सकता है, लेकिन मेरा मानना ​​है कि यह रास्ता आखिरकार समाधान तक ले जा सकता है। वैसे भी, मैं आपकी प्रतिक्रिया के लिए उत्सुक हूं।

( LaTeX अभिव्यक्तियों से चित्र बनाने के लिए इस अद्भुत साइट के लिए विशेष धन्यवाद )


क्या आप सुनिश्चित हैं कि आपकी असमानताएं उलट नहीं हैं? वह Sq> = P है? अर्थात्, किसी वर्ग की बम की कुल संख्या दी गई मैट्रिक्स से अधिक या उसके बराबर होती है।
डार्कस्की

1
जब एक रैखिक कार्यक्रम के चर पूर्णांक के लिए विवश होते हैं, तो हम उस "पूर्णांक रैखिक प्रोग्रामिंग" (आईपी) को कहते हैं। निरंतर मामले के विपरीत, आईपी एनपी-पूर्ण है। दुर्भाग्य से, सिंप्लेक्स एल्गोरिथ्म मदद नहीं करता है, जब तक कि एक अनुमान स्वीकार्य नहीं है। और आईपी पहले ही एक और जवाब में उल्लेख किया गया है
ब्लूराजा - डैनी पफ्लुगुएफ़ट

@ BlueRaja-DannyPflughoeft सही। "Despite the many crucial applications of this problem, and intense interest by researchers, no efficient algorithm is known for it.देखें पृष्ठ 254. पूर्णांक रैखिक प्रोग्रामिंग एक बहुत कठिन कम्प्यूटेशनल समस्या है। हमारे कुशल होने की एकमात्र आशा यह है कि आप अपने मैट्रिक्स एस के बारे में आंतरिक गुणों का दोहन करें। ऐसा बिल्कुल नहीं है
डार्कस्की

3

यह लालची समाधान सही प्रतीत होता है :

जैसा कि टिप्पणियों में बताया गया है, यह 2 डी में विफल हो जाएगा। लेकिन शायद आप इसे सुधार सकते हैं।

1 डी के लिए:
यदि कम से कम 2 नंबर हैं तो आपको सबसे बाईं ओर शूट करने की आवश्यकता नहीं है क्योंकि दूसरे पर शूटिंग करना बदतर नहीं है । इसलिए दूसरा शूट करें, जबकि पहले 0 नहीं है, क्योंकि आपको यह करना है। अगली सेल पर जाएँ। पिछले सेल के बारे में मत भूलना।

C ++ कोड:

void bombs(vector<int>& v, int i, int n){
    ans += n;
    v[i] -= n;
    if(i > 0)
        v[i - 1] -= n;
    if(i + 1< v.size())
        v[i + 1] -= n;
}

void solve(vector<int> v){
    int n = v.size();
    for(int i = 0; i < n;++i){
        if(i != n - 1){
            bombs(v, i + 1, v[i]);
        }
        else
            bombs(v, i, v[i])
    }
}

तो 2D के लिए:
फिर से: आपको पहली पंक्ति में शूटिंग करने की आवश्यकता नहीं है (यदि दूसरा है)। तो दूसरे को शूट करें। पहली पंक्ति के लिए 1 डी कार्य को हल करें। (क्योंकि आपको इसे अशक्त बनाने की आवश्यकता है)। नीचे जाओ। अंतिम पंक्ति मत भूलना।


5
एक प्रतिरूप "0110","1110","1110":। आप केवल 1 शॉट की जरूरत है, लेकिन मेरा मानना है कि आपका एल्गोरिथ्म 2. का प्रयोग करेंगे
maniek

2

बमों की संख्या को कम करने के लिए, हमें हर बम का प्रभाव अधिकतम करना होगा। इसे हासिल करने के लिए, हर कदम पर हमें सर्वश्रेष्ठ लक्ष्य का चयन करना होगा। प्रत्येक बिंदु के लिए यह योग है और यह आठ पड़ोसी हैं - इस बिंदु पर बमबारी की दक्षता मात्रा के रूप में इस्तेमाल किया जा सकता है। यह बमों के इष्टतम अनुक्रम के करीब प्रदान करेगा।

UPD : हमें शून्य की संख्या को भी ध्यान में रखना चाहिए, क्योंकि यह अक्षम है। वास्तव में समस्या यह है कि लगे हुए शून्य की संख्या को कम से कम किया जाए। लेकिन हम यह नहीं जान सकते कि कोई भी कदम हमें इस उद्देश्य के करीब कैसे पहुंचाता है। मैं इस विचार से सहमत हूं कि समस्या एनपी-पूर्ण है। मैं एक लालची दृष्टिकोण का सामना करता हूं, जो वास्तविक के करीब एक जवाब देगा।


यह इष्टतम नहीं है। काउंटर उदाहरण: 1010101, 0010100(शीर्ष पंक्ति, निचली पंक्ति) आपका दृष्टिकोण 3. की आवश्यकता होगी यह में 2. किया जा सकता है
Mysticial

2

मेरा मानना ​​है कि बमों की मात्रा को कम करने के लिए आपको केवल नुकसान की मात्रा को अधिकतम करने की आवश्यकता है .. इसके लिए उस क्षेत्र की जांच करने की आवश्यकता है जिसके पास सबसे मजबूत बल है .. इसलिए आप पहले एक 3x3 कर्नेल के साथ क्षेत्र का विश्लेषण करें और जांचें कि योग कहाँ है और मजबूत है .. और वहां बम है .. और जब तक मैदान समतल नहीं है .. तब तक इसके लिए जवाब 28 है

var oMatrix = [
[2,3,4,7,1],
[1,5,2,6,2],
[4,3,4,2,1],
[2,1,2,4,1],
[3,1,3,4,1],
[2,1,4,3,2],
[6,9,1,6,4]
]

var nBombs = 0;
do
{
    var bSpacesLeftToBomb = false;
    var nHigh = 0;
    var nCellX = 0;
    var nCellY = 0;
    for(var y = 1 ; y<oMatrix.length-1;y++) 
        for(var x = 1 ; x<oMatrix[y].length-1;x++)  
        {
            var nValue = 0;
            for(var yy = y-1;yy<=y+1;yy++)
                for(var xx = x-1;xx<=x+1;xx++)
                    nValue += oMatrix[yy][xx];

            if(nValue>nHigh)
            {
                nHigh = nValue;
                nCellX = x;
                nCellY = y; 
            }

        }
    if(nHigh>0)
    {
        nBombs++;

        for(var yy = nCellY-1;yy<=nCellY+1;yy++)
        {
            for(var xx = nCellX-1;xx<=nCellX+1;xx++)
            {
                if(oMatrix[yy][xx]<=0)
                    continue;
                oMatrix[yy][xx] = --oMatrix[yy][xx];
            }
        }
        bSpacesLeftToBomb = true;
    }
}
while(bSpacesLeftToBomb);

alert(nBombs+'bombs');

यह अन्य उत्तरों में से कुछ के समान ही एल्गोरिदम है, लेकिन बहुत बाद में।
Psr

@psr इतना ही नहीं। यह इष्टतम नहीं है।
५३ पर मिस्टिकियल

मैंने इसे पोस्ट किया, क्योंकि, जब यह एल्गोरिथम प्रस्तावित किया गया था, तो मुझे कोड या "अवधारणा के प्रोफेसर" का कोई पद नहीं मिला। इसलिए मैंने सोचा कि यह विवेक को मदद कर सकता है .. लेकिन .. btw @Mysticial क्या आपके पास यह है कि अधिक इष्टतम तरीका है?
CaldasGSM

@CaldasGSM कोई चिंता नहीं, मूल समस्या (अनुक्रमण के बिना) कठिन है। अब तक केवल एक ही उत्तर है जो इसे बेहतर तरीके से हल करता है, लेकिन यह घातीय समय में चलता है।
मिस्टिकल

2

यहां एक समाधान है जो कोनों के अच्छे गुणों को सामान्य करता है।

मान लेते हैं कि हमें दिए गए फ़ील्ड के लिए एक सही ड्रॉप पॉइंट मिल सकता है, अर्थात, इसमें मूल्य को कम करने का एक सबसे अच्छा तरीका है। फिर गिराए जाने वाले बमों की न्यूनतम संख्या का पता लगाने के लिए, एल्गोरिथ्म का पहला मसौदा हो सकता है (कोड एक रूबी कार्यान्वयन से कॉपी-पेस्ट किया गया है):

dropped_bomb_count = 0
while there_are_cells_with_non_zero_count_left
  coordinates = choose_a_perfect_drop_point
  drop_bomb(coordinates)
  dropped_bomb_count += 1
end
return dropped_bomb_count

चुनौती है choose_a_perfect_drop_point। सबसे पहले, आइए परिभाषित करें कि एक सही ड्रॉप बिंदु क्या है।

  • एक ड्रॉप बिंदु के लिए (x, y)में मूल्य कम हो जाती है (x, y)। यह अन्य कोशिकाओं में मूल्यों में कमी भी कर सकता है।
  • एक बूंद बिंदु एक के लिए (x, y)है बेहतर एक बूंद बिंदु से के लिए (x, y)अगर यह कोशिकाओं का एक उचित सुपरसेट कि में मान कम हो जाती है कम हो जाती है।
  • एक ड्रॉप प्वाइंट अधिकतम है अगर कोई अन्य बेहतर ड्रॉप प्वाइंट नहीं है।
  • यदि वे कोशिकाओं के समान सेट को घटाते हैं तो दो बूंद बिंदु बराबर(x, y) होते हैं ।
  • के लिए एक बूंद बिंदु (x, y)है सही है, तो इसके लिए सभी अधिक से अधिक ड्रॉप अंक के बराबर है (x, y)

अगर एक सही ड्रॉप पॉइंट है (x, y), तो आप किसी एक के लिए एक सही ड्रॉप पॉइंट (x, y)पर बम गिराने की तुलना में अधिक प्रभावी ढंग से मूल्य को कम नहीं कर सकते हैं (x, y)

किसी दिए गए फ़ील्ड के लिए एक सही ड्रॉप पॉइंट उसके किसी भी सेल के लिए एक सही ड्रॉप पॉइंट है।

यहाँ कुछ उदाहरण हैं:

1 0 1 0 0
0 0 0 0 0
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0

सेल (0, 0)(शून्य-आधारित सूचकांक) के लिए एकदम सही ड्रॉप पॉइंट है (1, 1)। के लिए सभी अन्य बूंद अंक (1, 1), वह यह है कि (0, 0), (0, 1), और (1, 0), कम कोशिकाओं में कमी।

0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0

सेल के लिए एक आदर्श ड्रॉप बिंदु (2, 2)(शून्य आधारित सूचकांक) है (2, 2), और यह भी सभी आसपास के कोशिकाओं (1, 1), (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2), और (3, 3)

0 0 0 0 1
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0

सेल के लिए एक सही ड्रॉप पॉइंट (2, 2)है (3, 1): यह मूल्य में (2, 2)और मूल्य में कमी करता है (4, 0)। अन्य सभी ड्रॉप पॉइंट (2, 2)अधिकतम नहीं हैं, क्योंकि वे एक सेल को कम करते हैं। के लिए सही ड्रॉप प्वाइंट (2, 2)भी सही ड्रॉप प्वाइंट है (4, 0), और यह क्षेत्र के लिए एकमात्र सही ड्रॉप प्वाइंट है। यह इस क्षेत्र (एक बम ड्रॉप) के लिए सही समाधान की ओर जाता है।

1 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
1 0 0 0 0

इसके लिए कोई सही ड्रॉप पॉइंट नहीं है (2, 2): दोनों (1, 1)और (1, 3)घटते हैं (2, 2)और एक और सेल (वे अधिकतम ड्रॉप पॉइंट हैं (2, 2))।, लेकिन वे बराबर नहीं हैं। हालाँकि, के (1, 1)लिए एक आदर्श ड्रॉप पॉइंट है (0, 0), और के (1, 3)लिए एक सही ड्रॉप पॉइंट है (0, 4)

सही ड्रॉप पॉइंट और चेक के एक निश्चित क्रम की परिभाषा के साथ, मुझे प्रश्न में उदाहरण के लिए निम्नलिखित परिणाम प्राप्त होते हैं:

Drop bomb on 1, 1
Drop bomb on 1, 1
Drop bomb on 1, 5
Drop bomb on 1, 5
Drop bomb on 1, 5
Drop bomb on 1, 6
Drop bomb on 1, 2
Drop bomb on 1, 2
Drop bomb on 0, 6
Drop bomb on 0, 6
Drop bomb on 2, 1
Drop bomb on 2, 5
Drop bomb on 2, 5
Drop bomb on 2, 5
Drop bomb on 3, 1
Drop bomb on 3, 0
Drop bomb on 3, 0
Drop bomb on 3, 0
Drop bomb on 3, 0
Drop bomb on 3, 0
Drop bomb on 3, 4
Drop bomb on 3, 4
Drop bomb on 3, 3
Drop bomb on 3, 3
Drop bomb on 3, 6
Drop bomb on 3, 6
Drop bomb on 3, 6
Drop bomb on 4, 6
28

हालाँकि, एल्गोरिथ्म केवल तभी काम करता है जब प्रत्येक चरण के बाद कम से कम एक सही ड्रॉप बिंदु हो। ऐसे उदाहरणों का निर्माण करना संभव है, जहाँ कोई सही ड्रॉप पॉइंट नहीं हैं:

0 1 1 0
1 0 0 1
1 0 0 1
0 1 1 0

इन मामलों के लिए, हम एल्गोरिथ्म को संशोधित कर सकते हैं ताकि एक सही ड्रॉप बिंदु के बजाय, हम अधिकतम ड्रॉप बिंदुओं के न्यूनतम विकल्प के साथ एक समन्वय का चयन करें, फिर प्रत्येक पसंद के लिए न्यूनतम गणना करें। उपरोक्त मामले में, मान वाले सभी कोशिकाओं में दो अधिकतम ड्रॉप बिंदु होते हैं। उदाहरण के लिए, (0, 1)अधिकतम ड्रॉप पॉइंट हैं (1, 1)और (1, 2)। किसी एक को चुनना और फिर न्यूनतम परिणाम प्राप्त करना

Drop bomb on 1, 1
Drop bomb on 2, 2
Drop bomb on 1, 2
Drop bomb on 2, 1
2

यह बहुत लालची एल्गोरिथ्म ऊपर प्रस्तुत किया गया है।

ठीक है, यह एक लालची एल्गोरिथ्म है, लेकिन कोनों और किनारों पर ध्यान केंद्रित करने के बजाय, मैंने परिभाषित किया कि अगली बूंद बिंदु कैसे चुनें। 5x7 के उदाहरण वर्ग के साथ, कोनों के बारे में बात करना आसान है, 1000x1000 क्षेत्र पर, इतना नहीं। यदि आप उस क्रम की जाँच करते हैं जिसमें मेरा एल्गोरिथ्म फ़ील्ड साफ़ करता है, तो यह बाहर से अंदर नहीं है, बल्कि ऊपर से नीचे / बाएँ से दाएं है।
तम्मो फ्रीज

2

यहाँ एक और विचार है:

आइए बोर्ड पर प्रत्येक स्थान के लिए एक वजन निर्धारित करके शुरू करें कि बम को गिराने से कितने नंबर कम हो जाएंगे। इसलिए यदि अंतरिक्ष में एक गैर-शून्य संख्या है, तो उसे एक बिंदु मिलता है, और यदि उससे सटे किसी स्थान पर गैर-शून्य संख्या है, तो उसे एक अतिरिक्त बिंदु मिलता है। इसलिए यदि 1000-बाई-1000 ग्रिड है, तो हमारे पास 1 मिलियन रिक्त स्थान में से एक वजन है।

फिर वजन द्वारा रिक्त स्थान की सूची को क्रमबद्ध करें, और सबसे अधिक वजन वाले बम को बम दें। यह हमारे हिरन के लिए सबसे धमाकेदार हो रहा है, इसलिए बोलने के लिए।

उसके बाद, हर उस जगह के वजन को अपडेट करें जिसका वजन बम से प्रभावित होता है। यह वह स्थान होगा, जिस पर आपने बमबारी की थी, और कोई भी स्थान तुरंत उसके समीप, और कोई भी स्थान तुरंत उन से सटे। दूसरे शब्दों में, किसी भी स्थान पर बमबारी से इसका मूल्य शून्य तक कम हो सकता था, या पड़ोसी स्थान का मूल्य शून्य तक कम हो सकता था।

फिर, सूची रिक्त स्थान को फिर से क्रमबद्ध करें। चूंकि रिक्त स्थान के केवल एक छोटे उपसमूह का वजन बमबारी से बदल गया था, आपको पूरी सूची का सहारा लेने की आवश्यकता नहीं होगी, बस उन लोगों को सूची में चारों ओर ले जाएं।

नए उच्चतम भार स्थान को बम बनाएं, और प्रक्रिया को दोहराएं।

यह गारंटी देता है कि प्रत्येक बमबारी संभव के रूप में कई रिक्त स्थान को कम कर देती है (मूल रूप से, यह कुछ रिक्त स्थान के रूप में हिट करता है जो पहले से ही शून्य हैं), इसलिए यह इष्टतम होगा, सिवाय इसके कि उनके वजन में संबंध हो सकते हैं। इसलिए आपको शीर्ष वजन के लिए टाई होने पर कुछ बैक ट्रैकिंग करने की आवश्यकता हो सकती है। केवल शीर्ष वजन के लिए एक टाई मायने रखती है, हालांकि, अन्य संबंध नहीं, इसलिए उम्मीद है कि यह बहुत पीछे नहीं है।

संपादित करें: नीचे दिए गए रहस्यवादी प्रतिदर्श यह दर्शाते हैं कि वास्तव में वजन में संबंधों की परवाह किए बिना यह इष्टतम होने की गारंटी नहीं है। कुछ मामलों में किसी दिए गए कदम में जितना संभव हो उतना वजन कम करना वास्तव में शेष बम को छोड़ देता है दूसरे चरण के बाद उच्च संचयी कमी को प्राप्त करने के लिए फैलता है क्योंकि आप पहले चरण में थोड़ा कम लालची विकल्प के साथ हो सकते हैं। मैं इस धारणा से कुछ गुमराह था कि परिणाम बमबारी के आदेश के प्रति असंवेदनशील हैं। वे हैं इस क्रम में असंवेदनशील कि आप बम विस्फोटों की किसी भी श्रृंखला को ले सकते हैं और उन्हें एक अलग क्रम में शुरू से फिर से खेलना और उसी परिणामी बोर्ड के साथ समाप्त कर सकते हैं। लेकिन यह इस बात का पालन नहीं करता है कि आप प्रत्येक बमबारी पर स्वतंत्र रूप से विचार कर सकते हैं। या, कम से कम, प्रत्येक बमबारी को इस तरह से विचार किया जाना चाहिए कि यह ध्यान में रखे कि बाद के बम विस्फोटों के लिए बोर्ड कितनी अच्छी तरह सेट होता है।


यह अभी भी बहुत पीछे होगा, शुरुआत में चूंकि खेतों में बहुत कम शून्य है, अधिकांश कोशिकाओं का वजन सभी खानों में होगा।
रेयान

हाँ, यह एक अच्छा बिंदु है, क्योंकि संभावित भार (केवल 0 से 9) में बड़ी रेंज नहीं है।
टिम गुडमैन

मुझे अभी भी 100% यकीन नहीं है कि बैकट्रैकिंग कितना आवश्यक है ... यह एक ग्रिड का निर्माण करने के लिए शिक्षाप्रद हो सकता है जहां लालची बमबारी का एक विकल्प लालची बमबारी की एक और पसंद से नीच है। हो सकता है कि अनुमान लगाने का कुछ सुसंगत तरीका हो जो बेहतर हो।
टिम गुडमैन

दरअसल, मुझे लगता है कि कर्नल पैनिक ने अपने जवाब में ऐसा किया है। एक लालची विकल्प दूसरे की तुलना में बेहतर हो सकता है, यह है कि एक व्यक्ति शेष संख्या को अधिक फैलता है।
टिम गुडमैन

3
1010101, 0010100एक प्रतिरूप हो सकता है जो इस दृष्टिकोण को गैर-इष्टतम साबित करता है। इस दृष्टिकोण की आवश्यकता है 3. यह 2 में किया जा सकता है
रहस्यवादी

1

ठीक है, मान लीजिए कि हम बोर्ड के पदों को 1, 2, ..., nx m नंबर देते हैं। बम के किसी भी क्रम को इस सेट में संख्याओं के अनुक्रम द्वारा दर्शाया जा सकता है, जहाँ संख्याएँ दोहरा सकती हैं। हालाँकि, बोर्ड पर प्रभाव समान है कि आप बमों को किस क्रम में गिराते हैं, इसलिए वास्तव में बम ड्रॉप्स की किसी भी पसंद को nxm संख्याओं की सूची के रूप में दर्शाया जा सकता है, जहाँ पहली संख्या स्थिति पर गिराए गए बमों की संख्या का प्रतिनिधित्व करती है। दूसरी संख्या स्थिति 2 पर गिराए गए बमों की संख्या का प्रतिनिधित्व करती है, आदि चलो nxm संख्याओं की इस सूची को "कुंजी" कहते हैं।

आप 1 बम ड्रॉप के परिणामस्वरूप सभी बोर्ड राज्यों की गणना करने की कोशिश कर सकते हैं, फिर इनका उपयोग सभी बोर्ड राज्यों की गणना करने के लिए कर सकते हैं जो 2 बम ड्रॉप आदि से उत्पन्न होते हैं, जब तक कि आपको सभी शून्य न मिलें। लेकिन प्रत्येक चरण में आप ऊपर बताए गए कुंजी का उपयोग करके राज्यों को कैश करेंगे, इसलिए आप इन परिणामों का उपयोग अगले चरण (एक "गतिशील प्रोग्रामिंग" दृष्टिकोण) की गणना में कर सकते हैं।

लेकिन ग्रिड में n, m, और संख्याओं के आकार के आधार पर, इस दृष्टिकोण की स्मृति आवश्यकताएं अत्यधिक हो सकती हैं। N + 1 के सभी परिणामों की गणना करने के बाद आप N बम ड्रॉप के लिए सभी परिणाम निकाल सकते हैं, इसलिए वहां कुछ बचत है। और निश्चित रूप से आप कुछ भी कैश नहीं कर सकते थे क्योंकि यह बहुत अधिक समय लेता है - गतिशील प्रोग्रामिंग दृष्टिकोण गति के लिए मेमोरी को ट्रेड करता है।


1
संदेह है कि यह तब से संभव है (यदि मैंने आपको सही तरीके से समझा)। n = एम। मुझे १० ^ ६ इंट पॉइंटर्स टू (१० ^ ६) ^ २ इंट सेल चाहिए। मेरे पास तालिका में कुंजियों के रूप में कई बोर्ड हैं। 10 ^ 12 संदेह मैं 32bit मशीन में इतना आवंटित कर सकता हूं।
abc

हाँ, मैंने आपकी टिप्पणियों को 1000 तक 1000 तक होने के बारे में देखा था। इसलिए कि प्रत्येक बोर्ड की स्थिति के लिए एक लाख ints, और प्रत्येक स्थान पर गिराए गए बमों की गिनती के लिए एक लाख ints। इसलिए आपके द्वारा संग्रहीत प्रत्येक बोर्ड के लिए, आपको 2 मिलियन ints की आवश्यकता है, और बहुत सारे संभावित बोर्ड हैं ...
टिम गुडमैन

मैंने एक दूसरा उत्तर जोड़ा है जो एक अलग दृष्टिकोण का उपयोग करता है।
टिम गुडमैन

1
हाँ। एक जानवर बल दृष्टिकोण की तरह है, लेकिन मुझे लगता है कि एक बड़े बोर्ड के लिए बहुत व्यावहारिक नहीं है।
टिम गुडमैन

@ कोस्टेक, इतना कम अनुमान क्यों? यह k ^ ^ (m * n) मेमोरी की तरह होता है जिसमें k को उन नंबरों के लिए सीमित किया जाता है जिन्हें बोर्ड शुरू में भरता है।
Rotsor

1

यदि आप बोर्ड को साफ करने के लिए पूर्ण इष्टतम समाधान चाहते हैं, तो आपको क्लासिक बैकट्रैकिंग का उपयोग करना होगा, लेकिन अगर मैट्रिक्स बहुत बड़ा है तो सबसे अच्छा समाधान खोजने में उम्र लग जाएगी, यदि आप "संभव" इष्टतम समाधान चाहते हैं तो आप लालची एल्गोरिथ्म का उपयोग कर सकते हैं। , अगर आपको एल्गोरिथ्म लिखने में मदद की जरूरत है तो मैं आपकी मदद कर सकता हूं

इसके बारे में सोचें जो सबसे अच्छा तरीका है। वहाँ एक और मैट्रिक्स बनाएँ, आप एक बम गिराकर आपके द्वारा हटाए गए बिंदुओं को स्टोर करते हैं और फिर अधिकतम बिंदुओं के साथ सेल को चुना और बम को ड्रॉप करते हुए पॉइंट मैट्रिक्स को अपडेट करें और जारी रखें। उदाहरण:

2 3 5 -> (2+(1*3)) (3+(1*5)) (5+(1*3))
1 3 2 -> (1+(1*4)) (3+(1*7)) (2+(1*4))
1 0 2 -> (1+(1*2)) (0+(1*5)) (2+(1*2))

प्रत्येक मान के लिए सेल वैल्यू +1, 0 से अधिक मूल्य वाले सेल के लिए


7
क्लासिक बैकट्रैकिंग का उपयोग करना होगा । क्या आपके पास इसके लिए कोई सबूत है?
शाहबाज

मुझे यकीन नहीं है। यह प्रतियोगिता मैं पिछले वर्ष () से तैयारी कर रहा हूं। सीमाएं 1 <= n, m <= 1000 हैं (पता नहीं कि बड़ा है या नहीं)। वैसे भी आपको सटीक उत्तर की आवश्यकता है (यह सीईआरसी प्रतियोगिता के समान है और इसी तरह)। समय सीमा को tho, कोई उत्तर नहीं, प्रतियोगिता पृष्ठ पर कोई समाधान नहीं दिया गया है।
abc

अच्छी तरह से हर दूसरे एल्गोरिदम आपको एक संभव इष्टतम समाधान देगा, लेकिन जब तक आप उन सभी को वापस करने की कोशिश नहीं करेंगे (तब तक आपको पता नहीं चलेगा कि यह समाधान सबसे अच्छा है
cosmin.danisor

2
आपको बैकट्रैकिंग का उपयोग करने की आवश्यकता नहीं है क्योंकि यह आपकी खोज का संयोजन है, क्रमपरिवर्तन का नहीं। बम गिराने का आदेश महत्वपूर्ण नहीं है
लुका रहने

तब आप लालची भिन्नता का उपयोग करके देख सकते हैं। हर कदम पर एक नई मैट्रिक्स बनाएं और हर बिंदु के बगल में प्रत्येक सेल के लिए उसके सेल + 1 का मान होगा> 0 इस तरह से बेहतर होगा कि अगला बम
कहां गिराया जाए

1

पाशविक बल !

मुझे पता है कि यह कुशल नहीं है, लेकिन फिर भी यदि आप एक तेज़ एल्गोरिथ्म पाते हैं, तो आप हमेशा इस परिणाम के खिलाफ परीक्षण कर सकते हैं कि यह कितना सही है।

कुछ पुनरावर्तन का उपयोग करें, जैसे:

void fn(tableState ts, currentlevel cl)
{
  // first check if ts is all zeros yet, if not:
  //
  // do a for loop to go through all cells of ts, 
  // for each cell do a bomb, and then
  // call: 
  // fn(ts, cl + 1);

}

कैशिंग द्वारा आप इसे और अधिक कुशल बना सकते हैं, यदि अलग-अलग तरीके से एक ही परिणाम प्राप्त होता है, तो आपको एक ही चरण नहीं दोहराना चाहिए।

समझाने के लिए:

यदि बम सेल 1,3,5 पर बमबारी सेल 5,3,1 के समान परिणाम होता है, तो, आपको दोनों मामलों के लिए अगले सभी चरणों को फिर से नहीं करना चाहिए, केवल 1 ही पर्याप्त है, आपको सभी को कहीं स्टोर करना चाहिए सारणी बताती है और इसके परिणामों का उपयोग करती है।

तालिका आँकड़ों के हैश का उपयोग तेजी से तुलना करने के लिए किया जा सकता है।


1
  1. कभी बॉर्डर बॉर्डर न करें (जब तक कि स्क्वायर में नॉनबॉर्ड पड़ोसी न हो)
  2. शून्य कोना।
  3. शून्य कोने के लिए, एक वर्ग दूर तिरछे (एकमात्र नॉनबॉर्डर पड़ोसी) कोने के मूल्य को छोड़ दें
  4. इससे नए कोने पैदा होंगे। 2 पर जाएं

संपादित करें: ध्यान नहीं दिया कि कोस्टेक ने लगभग एक ही दृष्टिकोण का सुझाव दिया था, इसलिए अब मैं मजबूत दावा करता हूं: यदि स्पष्ट कोनों को हमेशा सबसे बाहरी परत पर चुना जाता है, तो यह इष्टतम है।

ओपी के उदाहरण में: 5 पर किसी भी चीज़ पर 2 (1 + 1 या 2 के रूप में) छोड़ने से 5 पर गिराने वाले किसी भी वर्ग को मारने की ओर नहीं जाता है। तो हमें बस 5 पर 2 छोड़ना चाहिए (और निचले बाएं 1 पर 6 ...)

इसके बाद, केवल एक ही तरीका है कि कैसे (शीर्ष बाएं में) को साफ़ करें कि मूल 1 (अब 0) क्या था, और यह बी 3 पर 0 (जैसे नोटेशन की तरह एक्सेल) छोड़ने के द्वारा है। और इसी तरह।

पूरे ए और ई कॉलम और 1 और 7 पंक्तियों को साफ़ करने के बाद ही, एक परत को गहराई से साफ़ करना शुरू करें।

केवल उन जानबूझकर साफ़ किए गए पर विचार करें, 0 मूल्य के कोनों को साफ़ करने से कुछ भी खर्च नहीं होता है और इसके बारे में सोचना सरल हो जाता है।

क्योंकि इस तरह से गिराए गए सभी बमों को गिरा दिया जाना चाहिए और इससे साफ हो चुके खेतों की ओर बढ़ जाता है, यह इष्टतम समाधान है।


अच्छी नींद के बाद मुझे एहसास हुआ कि यह सच नहीं है। विचार करें

  ABCDE    
1 01000
2 10000
3 00000
4 00000

मेरा दृष्टिकोण बी 3 और सी 2 पर बम गिराएगा, जब बी 2 पर ड्रॉप करना पर्याप्त होगा


लेकिन क्या यह इष्टतम है?
रहस्यमयी

7
नए कोनों को 2 तरीकों से बम बनाया जा सकता है (यदि अधिकांश कोने बिंदु में सभी 4 मानों में से सबसे कम है)। इष्टतम बमबारी कौन सी है?
abc

मैं इसी तरह के दृष्टिकोण के बारे में सोच रहा था, और जब आप कोस्टेक जैसी स्थिति तक पहुंचते हैं, तो बैकट्रैकिंग का उपयोग करना शुरू करें ...
कार्ली होर्वाथ

कोनों आपको विकर्ण वर्ग पर गिराए जाने के लिए न्यूनतम मात्रा में बम देते हैं। लेकिन एक बार जब आप उन्हें शून्य कर देते हैं, तो अगली सीमा टाइल के लिए आवश्यक रूप से स्पष्ट इष्टतम बिंदु नहीं होगा। हालांकि यह खोज स्थान को कम करने का एक अच्छा तरीका है।
यूजीन

नए कोने के विकर्ण को चुनने के बारे में क्या है जो हिट बॉक्स में उच्चतम कुल गणना करता है?
जज मेगार्डन

1

यहाँ मेरा समाधान है .. मैं इसे अभी तक कोड में नहीं लिखूंगा क्योंकि मेरे पास समय नहीं है, लेकिन मेरा मानना ​​है कि इसे हर बार एक इष्टतम संख्या में चालें पैदा करनी चाहिए - हालांकि मुझे यकीन नहीं है कि यह खोजने में कितना कुशल होगा। बम के लिए अंक।

सबसे पहले, जैसा कि @Luka Rahne ने एक टिप्पणी में कहा, जिस क्रम में आप बम बनाते हैं वह महत्वपूर्ण नहीं है- केवल संयोजन।

दूसरे, जैसा कि कई अन्य लोगों ने कहा है, कोनों से 1-विकर्ण पर बमबारी करना इष्टतम है क्योंकि यह कोनों से अधिक बिंदुओं को छूता है।

यह एल्गोरिथ्म के मेरे संस्करण का आधार बनाता है: हम 'कोनों से 1-ऑफ को पहले या अंतिम पर बमबारी कर सकते हैं, इससे कोई फर्क नहीं पड़ता है (सिद्धांत रूप में) हम पहले उन पर बमबारी करते हैं क्योंकि यह बाद के निर्णयों को आसान बनाता है (व्यवहार में) हम उस बिंदु पर बम लगाते हैं जो सबसे अधिक अंक को प्रभावित करता है, साथ ही साथ उन कोनों पर बमबारी करता है।

आइए बोर्ड में सबसे गैर-बमवर्णीय बिंदुओं के साथ अंक के प्रतिरोध को परिभाषित करें + उनके आसपास 0 की सबसे बड़ी संख्या

गैर-बमनीय बिंदुओं को उन बिंदुओं के रूप में परिभाषित किया जा सकता है जो हमारे द्वारा देखे जा रहे बोर्ड के हमारे वर्तमान दायरे में मौजूद नहीं हैं ।

मैं 4 सीमाओं को भी परिभाषित करूंगा जो हमारे दायरे को संभालेंगी: टॉप = 0, लेफ्ट = 0, बॉटम = के, राइट = जे। (मान शुरू करने के लिए)

अंत में, मैं इष्टतम बमों को उन बमों के रूप में परिभाषित करूंगा जो उन बिंदुओं पर गिराए जाते हैं जो प्रतिरोध के बिंदुओं से सटे होते हैं और प्रतिरोध के उच्चतम मूल्यवान बिंदु (1) को छू रहे हैं और (2) संभव सबसे बड़ी संख्या है।

दृष्टिकोण के बारे में- यह स्पष्ट है कि हम बाहर से काम कर रहे हैं। हम एक ही समय में 4 'बॉम्बर्स' के साथ काम कर पाएंगे।

प्रतिरोध के पहले बिंदु जाहिर तौर पर हमारे कोने हैं। 'आऊट ऑफ बाउंड' पॉइंट्स बमने योग्य नहीं हैं (प्रत्येक कोने के दायरे से बाहर 5 पॉइंट हैं)। इसलिए हम पहले कोनों से तिरछे एक बिंदु पर बम लगाते हैं।

कलन विधि:

  1. 4 इष्टतम बम बिंदु खोजें।
  2. यदि एक बम बिंदु एक प्रतिरोध बिंदु पर बमबारी कर रहा है जो 2 सीमा (यानी एक कोने) को छू रहा है, तो उस बिंदु तक बम 0. है। अन्यथा, प्रत्येक बम को तब तक बम करें जब तक कि इष्टतम बम बिंदु को छूने वाले प्रतिरोध के बिंदुओं में से एक 0 न हो।
  3. प्रत्येक बाउंड के लिए: यदि (राशि (बाउंड) == 0) अग्रिम बाउंड

टॉप = बॉटम और लेफ्ट = राइट तक दोहराएं

मैं वास्तविक कोड को बाद में लिखने की कोशिश करूंगा


1

आप राज्य अंतरिक्ष योजना का उपयोग कर सकते हैं। उदाहरण के लिए, A * (या इसके किसी एक संस्करण) का उपयोग करके f = g + hइस तरह से एक अनुमान के साथ युग्मित :

  • g: अब तक गिराए गए बमों की संख्या
  • एच: 9 से विभाजित ग्रिड के सभी मूल्यों पर योग (जो सबसे अच्छा परिणाम है, जिसका अर्थ है कि हमारे पास एक स्वीकार्य उत्तराधिकार है)

1

मुझे 28 मूव भी मिले। मैंने सबसे अच्छे अगले कदम के लिए दो परीक्षणों का इस्तेमाल किया: पहला कदम बोर्ड के लिए न्यूनतम राशि का उत्पादन। दूसरा, समान राशि के लिए, अधिकतम घनत्व उत्पन्न करने वाली चाल, के रूप में परिभाषित:

number-of-zeros / number-of-groups-of-zeros

यह हास्केल है। "सॉल्विंग बोर्ड" इंजन के समाधान को दर्शाता है। आप "मुख्य" टाइप करके खेल खेल सकते हैं, फिर एक लक्ष्य बिंदु दर्ज करें, एक सिफारिश के लिए "सबसे अच्छा", या छोड़ने के लिए "छोड़ दिया"।

OUTPUT:
* मुख्य> हल बोर्ड
[(4,4), (3,6), (3,3), (2,2), (2,2), (4,6), (4,6), (2,6), (3,2), (4,2), (2,6), (3,3), (4,3), (2,6), (4,2), (4 , 6), (4,6), (3,6), (2,6), (2,6), (2,4), (2,4), (2,6), (3,6 ), (4,2), (4,2), (4,2), (4,2)]

import Data.List
import Data.List.Split
import Data.Ord
import Data.Function(on)

board = [2,3,4,7,1,
         1,5,2,6,2,
         4,3,4,2,1,
         2,1,2,4,1,
         3,1,3,4,1,
         2,1,4,3,2,
         6,9,1,6,4]

n = 5
m = 7

updateBoard board pt =
  let x = fst pt
      y = snd pt
      precedingLines = replicate ((y-2) * n) 0
      bomb = concat $ replicate (if y == 1
                                    then 2
                                    else min 3 (m+2-y)) (replicate (x-2) 0 
                                                         ++ (if x == 1 
                                                                then [1,1]
                                                                else replicate (min 3 (n+2-x)) 1)
                                                                ++ replicate (n-(x+1)) 0)
  in zipWith (\a b -> max 0 (a-b)) board (precedingLines ++ bomb ++ repeat 0)

showBoard board = 
  let top = "   " ++ (concat $ map (\x -> show x ++ ".") [1..n]) ++ "\n"
      chunks = chunksOf n board
  in putStrLn (top ++ showBoard' chunks "" 1)
       where showBoard' []     str count = str
             showBoard' (x:xs) str count =
               showBoard' xs (str ++ show count ++ "." ++ show x ++ "\n") (count+1)

instances _ [] = 0
instances x (y:ys)
  | x == y    = 1 + instances x ys
  | otherwise = instances x ys

density a = 
  let numZeros = instances 0 a
      groupsOfZeros = filter (\x -> head x == 0) (group a)
  in if null groupsOfZeros then 0 else numZeros / fromIntegral (length groupsOfZeros)

boardDensity board = sum (map density (chunksOf n board))

moves = [(a,b) | a <- [2..n-1], b <- [2..m-1]]               

bestMove board = 
  let lowestSumMoves = take 1 $ groupBy ((==) `on` snd) 
                              $ sortBy (comparing snd) (map (\x -> (x, sum $ updateBoard board x)) (moves))
  in if null lowestSumMoves
        then (0,0)
        else let lowestSumMoves' = map (\x -> fst x) (head lowestSumMoves) 
             in fst $ head $ reverse $ sortBy (comparing snd) 
                (map (\x -> (x, boardDensity $ updateBoard board x)) (lowestSumMoves'))   

solve board = solve' board [] where
  solve' board result
    | sum board == 0 = result
    | otherwise      = 
        let best = bestMove board 
        in solve' (updateBoard board best) (result ++ [best])

main :: IO ()
main = mainLoop board where
  mainLoop board = do 
    putStrLn ""
    showBoard board
    putStr "Pt: "
    a <- getLine
    case a of 
      "quit"    -> do putStrLn ""
                      return ()
      "best"    -> do putStrLn (show $ bestMove board)
                      mainLoop board
      otherwise -> let ws = splitOn "," a
                       pt = (read (head ws), read (last ws))
                   in do mainLoop (updateBoard board pt)

1

ऐसा लगता है कि यहां एक गैरबिपेटाइट मैचिंग सबस्ट्रक्चर है। निम्नलिखित उदाहरण पर विचार करें:

0010000
1000100
0000001
1000000
0000001
1000100
0010000

इस मामले के लिए इष्टतम समाधान का आकार 5 है, क्योंकि इसके किनारों द्वारा 9-चक्र के कोने के न्यूनतम कवर का आकार है।

यह मामला, विशेष रूप से, दिखाता है कि कुछ लोगों ने जो रैखिक प्रोग्रामिंग विश्राम पोस्ट किया है, वह सटीक नहीं है, काम नहीं करता है, और उन सभी बुरी चीजों को। मुझे पूरा यकीन है कि मैं आपकी समस्या को कम से कम कुछ किनारों द्वारा अपने प्लानेर क्यूबिक ग्राफ के वर्टिकल को कम कर सकता हूं ”, जिससे मुझे संदेह होता है कि क्या कोई लालची / पहाड़ी-चढ़ाई समाधान काम करने वाला है।

मुझे सबसे खराब स्थिति में बहुपद समय में इसे हल करने का कोई तरीका नहीं दिखता है। एक बहुत ही चतुर बाइनरी-सर्च-एंड-डीपी समाधान हो सकता है जो मैं नहीं देख रहा हूं।

संपादित करें : मैं देखता हूं कि प्रतियोगिता ( http://deadline24.pl ) भाषा-अज्ञेयवादी है; वे आपको इनपुट फ़ाइलों का एक गुच्छा भेजते हैं और आप उन्हें आउटपुट भेजते हैं। तो आपको ऐसी किसी चीज़ की ज़रूरत नहीं है जो सबसे खराब स्थिति वाले बहुपद में चलती है। विशेष रूप से, आपको इनपुट देखने को मिलता है !

इनपुट में छोटे मामलों का एक गुच्छा है। फिर 10x1000 का मामला, 100x100 का मामला और 1000x1000 का मामला है। तीन बड़े मामलों में सभी बहुत अच्छी तरह से व्यवहार कर रहे हैं। क्षैतिज रूप से आसन्न प्रविष्टियों में आमतौर पर समान मूल्य होता है। अपेक्षाकृत गोमांस मशीन पर, मैं केवल एक-दो मिनटों में CPLEX का उपयोग करके सभी मामलों को हल करने में सक्षम हूँ। मैं 1000x1000 पर भाग्यशाली निकला; एलपी छूट एक अभिन्न इष्टतम समाधान है। मेरे समाधान .ansपरीक्षण डेटा बंडल में प्रदान की गई फ़ाइलों से सहमत हैं ।

मैं शर्त लगा सकता हूँ कि यदि आपने इस पर एक नज़र डाला, तो आप इनपुट की संरचना का उपयोग अधिक प्रत्यक्ष तरीके से कर सकते हैं; ऐसा लगता है जैसे आप पहली पंक्ति, या दो, या तीन को बार-बार छोड़ सकते हैं जब तक कि आपको कुछ भी नहीं मिला है। (लगता है, 1000x1000 में, सभी पंक्तियाँ न के बराबर हैं? मुझे लगता है कि आपका "भाग" कहाँ से है?)


हाँ। कभी-कभी मैं सिर्फ पाठ के "अप्रासंगिक" भाग को छोड़ देता हूं। बस संक्षेप में विचार और इतने पर मिलता है। इस बार यह मूल रूप से स्तर को आसान से कठिन के रूप में नरक में बदल देता है: पी वैसे भी मुझे पता है कि आप एक हेयुरिस्टिक होने के लिए "ज्ञात" इनपुट सेट बनाने की कोशिश कर सकते हैं। दूसरी ओर मैं सिर्फ यह सोचता हूं कि यदि उत्तर प्रतिशत अंक नहीं है, तो कुछ एल्गोरिदम होना चाहिए जो आसानी से 5h के दौरान प्रदर्शन करेंगे। मैंने पाया कि बहुत बड़ी जटिलता थी। तब मैंने इसे अधिक ध्यान से पढ़ा, जब किसी ने उत्पत्ति के बारे में पूछा :)
abc

हम यह कह सकते हैं कि बहुत से लोगों को अच्छी समस्या है, जिसके बारे में सोचने के लिए, लेकिन संदेह है कि यह बहुपद समय में हो सकता है। यह मज़ेदार है कि एक साधारण बाधा, आसान से असंभव तक के कार्य स्तर को बदल देती है।
एबीसी

@Kostek: क्षमा करें यदि मैं अस्पष्ट था। मैं ... दर्शकों के लिए एक उपयुक्त स्तर पर स्पष्टीकरण पिचिंग में बहुत बुरा हूं। :) मैं कहाँ अस्पष्ट था?
tmyklebu

1

मैं अपनी सर्वश्रेष्ठ उत्तराधिकारी का उपयोग करके बमबारी अभियान की गणना किए बिना वास्तविक संख्या की गणना करने के तरीके के बारे में नहीं सोच सकता हूं और आशा करता हूं कि मुझे उचित परिणाम मिलेगा।

तो मेरी विधि प्रत्येक सेल के लिए एक बमबारी दक्षता मीट्रिक की गणना करना है, सेल को उच्चतम मूल्य के साथ बम बनाना है, .... जब तक मैंने सब कुछ समतल नहीं किया है, तब तक प्रक्रिया को पुन: व्यवस्थित करें। कुछ लोगों ने साधारण संभावित क्षति (यानी 0 से 9 तक स्कोर) को एक मीट्रिक के रूप में उपयोग करने की वकालत की है, लेकिन यह उच्च मूल्य कोशिकाओं को पाउंड करके और क्षति ओवरलैप का उपयोग नहीं करने से कम हो जाती है। मैं गणना करता हूं cell value - sum of all neighbouring cells, किसी भी सकारात्मक को 0 पर रीसेट करता हूं और किसी भी चीज के नकारात्मक मूल्य का पूर्ण उपयोग करता हूं । सहज रूप से इस मीट्रिक को एक चयन करना चाहिए जो सीधे उन लोगों को पाउंड करने के बजाय उच्च मात्रा के साथ कोशिकाओं पर क्षति को अधिकतम करने में मदद करता है।

नीचे दिए गए कोड 28 बमों में परीक्षण क्षेत्र के कुल विनाश तक पहुंचते हैं (ध्यान दें कि मीट्रिक पैदावार 31 के रूप में संभावित नुकसान का उपयोग करते हुए!)।

using System;
using System.Collections.Generic;
using System.Linq;

namespace StackOverflow
{
  internal class Program
  {
    // store the battle field as flat array + dimensions
    private static int _width = 5;
    private static int _length = 7;
    private static int[] _field = new int[] {
        2, 3, 4, 7, 1,
        1, 5, 2, 6, 2,
        4, 3, 4, 2, 1,
        2, 1, 2, 4, 1,
        3, 1, 3, 4, 1,
        2, 1, 4, 3, 2,
        6, 9, 1, 6, 4
    };
    // this will store the devastation metric
    private static int[] _metric;

    // do the work
    private static void Main(string[] args)
    {
        int count = 0;

        while (_field.Sum() > 0)
        {
            Console.Out.WriteLine("Round {0}:", ++count);
            GetBlastPotential();
            int cell_to_bomb = FindBestBombingSite();
            PrintField(cell_to_bomb);
            Bomb(cell_to_bomb);
        }
        Console.Out.WriteLine("Done in {0} rounds", count);
    } 

    // convert 2D position to 1D index
    private static int Get1DCoord(int x, int y)
    {
        if ((x < 0) || (y < 0) || (x >= _width) || (y >= _length)) return -1;
        else
        {
            return (y * _width) + x;
        }
    }

    // Convert 1D index to 2D position
    private static void Get2DCoord(int n, out int x, out int y)
    {
        if ((n < 0) || (n >= _field.Length))
        {
            x = -1;
            y = -1;
        }
        else
        {
            x = n % _width;
            y = n / _width;
        }
    }

    // Compute a list of 1D indices for a cell neighbours
    private static List<int> GetNeighbours(int cell)
    {
        List<int> neighbours = new List<int>();
        int x, y;
        Get2DCoord(cell, out x, out y);
        if ((x >= 0) && (y >= 0))
        {
            List<int> tmp = new List<int>();
            tmp.Add(Get1DCoord(x - 1, y - 1));
            tmp.Add(Get1DCoord(x - 1, y));
            tmp.Add(Get1DCoord(x - 1, y + 1));
            tmp.Add(Get1DCoord(x, y - 1));
            tmp.Add(Get1DCoord(x, y + 1));
            tmp.Add(Get1DCoord(x + 1, y - 1));
            tmp.Add(Get1DCoord(x + 1, y));
            tmp.Add(Get1DCoord(x + 1, y + 1));

            // eliminate invalid coords - i.e. stuff past the edges
            foreach (int c in tmp) if (c >= 0) neighbours.Add(c);
        }
        return neighbours;
    }

    // Compute the devastation metric for each cell
    // Represent the Value of the cell minus the sum of all its neighbours
    private static void GetBlastPotential()
    {
        _metric = new int[_field.Length];
        for (int i = 0; i < _field.Length; i++)
        {
            _metric[i] = _field[i];
            List<int> neighbours = GetNeighbours(i);
            if (neighbours != null)
            {
                foreach (int j in neighbours) _metric[i] -= _field[j];
            }
        }
        for (int i = 0; i < _metric.Length; i++)
        {
            _metric[i] = (_metric[i] < 0) ? Math.Abs(_metric[i]) : 0;
        }
    }

    //// Compute the simple expected damage a bomb would score
    //private static void GetBlastPotential()
    //{
    //    _metric = new int[_field.Length];
    //    for (int i = 0; i < _field.Length; i++)
    //    {
    //        _metric[i] = (_field[i] > 0) ? 1 : 0;
    //        List<int> neighbours = GetNeighbours(i);
    //        if (neighbours != null)
    //        {
    //            foreach (int j in neighbours) _metric[i] += (_field[j] > 0) ? 1 : 0;
    //        }
    //    }            
    //}

    // Update the battle field upon dropping a bomb
    private static void Bomb(int cell)
    {
        List<int> neighbours = GetNeighbours(cell);
        foreach (int i in neighbours)
        {
            if (_field[i] > 0) _field[i]--;
        }
    }

    // Find the best bombing site - just return index of local maxima
    private static int FindBestBombingSite()
    {
        int max_idx = 0;
        int max_val = int.MinValue;
        for (int i = 0; i < _metric.Length; i++)
        {
            if (_metric[i] > max_val)
            {
                max_val = _metric[i];
                max_idx = i;
            }
        }
        return max_idx;
    }

    // Display the battle field on the console
    private static void PrintField(int cell)
    {
        for (int x = 0; x < _width; x++)
        {
            for (int y = 0; y < _length; y++)
            {
                int c = Get1DCoord(x, y);
                if (c == cell)
                    Console.Out.Write(string.Format("[{0}]", _field[c]).PadLeft(4));
                else
                    Console.Out.Write(string.Format(" {0} ", _field[c]).PadLeft(4));
            }
            Console.Out.Write(" || ");
            for (int y = 0; y < _length; y++)
            {
                int c = Get1DCoord(x, y);
                if (c == cell)
                    Console.Out.Write(string.Format("[{0}]", _metric[c]).PadLeft(4));
                else
                    Console.Out.Write(string.Format(" {0} ", _metric[c]).PadLeft(4));
            }
            Console.Out.WriteLine();
        }
        Console.Out.WriteLine();
    }           
  }
}

परिणामस्वरूप बमबारी पैटर्न निम्नानुसार आउटपुट है (बाईं ओर फ़ील्ड मान, दाईं ओर मीट्रिक)

Round 1:
  2   1   4   2   3   2   6  ||   7  16   8  10   4  18   6
  3   5   3   1   1   1   9  ||  11  18  18  21  17  28   5
  4  [2]  4   2   3   4   1  ||  19 [32] 21  20  17  24  22
  7   6   2   4   4   3   6  ||   8  17  20  14  16  22   8
  1   2   1   1   1   2   4  ||  14  15  14  11  13  16   7

Round 2:
  2   1   4   2   3   2   6  ||   5  13   6   9   4  18   6
  2   4   2   1   1  [1]  9  ||  10  15  17  19  17 [28]  5
  3   2   3   2   3   4   1  ||  16  24  18  17  17  24  22
  6   5   1   4   4   3   6  ||   7  14  19  12  16  22   8
  1   2   1   1   1   2   4  ||  12  12  12  10  13  16   7

Round 3:
  2   1   4   2   2   1   5  ||   5  13   6   7   3  15   5
  2   4   2   1   0   1   8  ||  10  15  17  16  14  20   2
  3  [2]  3   2   2   3   0  ||  16 [24] 18  15  16  21  21
  6   5   1   4   4   3   6  ||   7  14  19  11  14  19   6
  1   2   1   1   1   2   4  ||  12  12  12  10  13  16   7

Round 4:
  2   1   4   2   2   1   5  ||   3  10   4   6   3  15   5
  1   3   1   1   0   1   8  ||   9  12  16  14  14  20   2
  2   2   2   2   2  [3]  0  ||  13  16  15  12  16 [21] 21
  5   4   0   4   4   3   6  ||   6  11  18   9  14  19   6
  1   2   1   1   1   2   4  ||  10   9  10   9  13  16   7

Round 5:
  2   1   4   2   2   1   5  ||   3  10   4   6   2  13   3
  1   3   1   1   0  [0]  7  ||   9  12  16  13  12 [19]  2
  2   2   2   2   1   3   0  ||  13  16  15  10  14  15  17
  5   4   0   4   3   2   5  ||   6  11  18   7  13  17   6
  1   2   1   1   1   2   4  ||  10   9  10   8  11  13   5

Round 6:
  2   1   4   2   1   0   4  ||   3  10   4   5   2  11   2
  1   3   1   1   0   0   6  ||   9  12  16  11   8  13   0
  2   2   2   2   0   2   0  ||  13  16  15   9  14  14  15
  5   4  [0]  4   3   2   5  ||   6  11 [18]  6  11  15   5
  1   2   1   1   1   2   4  ||  10   9  10   8  11  13   5

Round 7:
  2   1   4   2   1   0   4  ||   3  10   4   5   2  11   2
  1   3   1   1   0   0   6  ||   8  10  13   9   7  13   0
  2  [1]  1   1   0   2   0  ||  11 [15] 12   8  12  14  15
  5   3   0   3   3   2   5  ||   3   8  10   3   8  15   5
  1   1   0   0   1   2   4  ||   8   8   7   7   9  13   5

Round 8:
  2   1   4   2   1   0   4  ||   1   7   2   4   2  11   2
  0   2   0   1   0   0   6  ||   7   7  12   7   7  13   0
  1   1   0   1   0   2   0  ||   8   8  10   6  12  14  15
  4   2   0   3   3  [2]  5  ||   2   6   8   2   8 [15]  5
  1   1   0   0   1   2   4  ||   6   6   6   7   9  13   5

Round 9:
  2   1   4   2   1   0   4  ||   1   7   2   4   2  11   2
  0   2   0   1   0   0   6  ||   7   7  12   7   6  12   0
  1   1   0   1   0  [1]  0  ||   8   8  10   5  10 [13] 13
  4   2   0   3   2   2   4  ||   2   6   8   0   6   9   3
  1   1   0   0   0   1   3  ||   6   6   6   5   8  10   4

Round 10:
  2   1   4   2   1   0   4  ||   1   7   2   4   2  10   1
  0   2  [0]  1   0   0   5  ||   7   7 [12]  7   6  11   0
  1   1   0   1   0   1   0  ||   8   8  10   4   8   9  10
  4   2   0   3   1   1   3  ||   2   6   8   0   6   8   3
  1   1   0   0   0   1   3  ||   6   6   6   4   6   7   2

Round 11:
  2   0   3   1   1   0   4  ||   0   6   0   3   0  10   1
  0   1   0   0   0  [0]  5  ||   4   5   5   5   3 [11]  0
  1   0   0   0   0   1   0  ||   6   8   6   4   6   9  10
  4   2   0   3   1   1   3  ||   1   5   6   0   5   8   3
  1   1   0   0   0   1   3  ||   6   6   6   4   6   7   2

Round 12:
  2   0   3   1   0   0   3  ||   0   6   0   2   1   7   1
  0   1   0   0   0   0   4  ||   4   5   5   4   1   7   0
  1   0   0   0   0  [0]  0  ||   6   8   6   4   5  [9]  8
  4   2   0   3   1   1   3  ||   1   5   6   0   4   7   2
  1   1   0   0   0   1   3  ||   6   6   6   4   6   7   2

Round 13:
  2   0   3   1   0   0   3  ||   0   6   0   2   1   6   0
  0   1   0   0   0   0   3  ||   4   5   5   4   1   6   0
  1  [0]  0   0   0   0   0  ||   6  [8]  6   3   3   5   5
  4   2   0   3   0   0   2  ||   1   5   6   0   4   6   2
  1   1   0   0   0   1   3  ||   6   6   6   3   4   4   0

Round 14:
  2   0   3   1   0  [0]  3  ||   0   5   0   2   1  [6]  0
  0   0   0   0   0   0   3  ||   2   5   4   4   1   6   0
  0   0   0   0   0   0   0  ||   4   4   4   3   3   5   5
  3   1   0   3   0   0   2  ||   0   4   5   0   4   6   2
  1   1   0   0   0   1   3  ||   4   4   5   3   4   4   0

Round 15:
  2   0   3   1   0   0   2  ||   0   5   0   2   1   4   0
  0   0   0   0   0   0   2  ||   2   5   4   4   1   4   0
  0   0   0   0   0   0   0  ||   4   4   4   3   3   4   4
  3   1   0   3   0  [0]  2  ||   0   4   5   0   4  [6]  2
  1   1   0   0   0   1   3  ||   4   4   5   3   4   4   0

Round 16:
  2  [0]  3   1   0   0   2  ||   0  [5]  0   2   1   4   0
  0   0   0   0   0   0   2  ||   2   5   4   4   1   4   0
  0   0   0   0   0   0   0  ||   4   4   4   3   3   3   3
  3   1   0   3   0   0   1  ||   0   4   5   0   3   3   1
  1   1   0   0   0   0   2  ||   4   4   5   3   3   3   0

Round 17:
  1   0   2   1   0   0   2  ||   0   3   0   1   1   4   0
  0   0   0   0   0   0   2  ||   1   3   3   3   1   4   0
  0   0   0   0   0   0   0  ||   4   4   4   3   3   3   3
  3   1  [0]  3   0   0   1  ||   0   4  [5]  0   3   3   1
  1   1   0   0   0   0   2  ||   4   4   5   3   3   3   0

Round 18:
  1   0   2   1   0   0   2  ||   0   3   0   1   1   4   0
  0   0   0   0   0   0   2  ||   1   3   3   3   1   4   0
  0   0   0   0   0   0   0  ||   3   3   2   2   2   3   3
  3  [0]  0   2   0   0   1  ||   0  [4]  2   0   2   3   1
  1   0   0   0   0   0   2  ||   2   4   2   2   2   3   0

Round 19:
  1   0   2   1   0  [0]  2  ||   0   3   0   1   1  [4]  0
  0   0   0   0   0   0   2  ||   1   3   3   3   1   4   0
  0   0   0   0   0   0   0  ||   2   2   2   2   2   3   3
  2   0   0   2   0   0   1  ||   0   2   2   0   2   3   1
  0   0   0   0   0   0   2  ||   2   2   2   2   2   3   0

Round 20:
  1  [0]  2   1   0   0   1  ||   0  [3]  0   1   1   2   0
  0   0   0   0   0   0   1  ||   1   3   3   3   1   2   0
  0   0   0   0   0   0   0  ||   2   2   2   2   2   2   2
  2   0   0   2   0   0   1  ||   0   2   2   0   2   3   1
  0   0   0   0   0   0   2  ||   2   2   2   2   2   3   0

Round 21:
  0   0   1   1   0   0   1  ||   0   1   0   0   1   2   0
  0   0   0   0   0   0   1  ||   0   1   2   2   1   2   0
  0   0   0   0   0   0   0  ||   2   2   2   2   2   2   2
  2   0   0   2   0  [0]  1  ||   0   2   2   0   2  [3]  1
  0   0   0   0   0   0   2  ||   2   2   2   2   2   3   0

Round 22:
  0   0   1   1   0   0   1  ||   0   1   0   0   1   2   0
  0   0   0   0   0   0   1  ||   0   1   2   2   1   2   0
 [0]  0   0   0   0   0   0  ||  [2]  2   2   2   2   1   1
  2   0   0   2   0   0   0  ||   0   2   2   0   2   1   1
  0   0   0   0   0   0   1  ||   2   2   2   2   2   1   0

Round 23:
  0   0   1   1   0   0   1  ||   0   1   0   0   1   2   0
  0   0  [0]  0   0   0   1  ||   0   1  [2]  2   1   2   0
  0   0   0   0   0   0   0  ||   1   1   2   2   2   1   1
  1   0   0   2   0   0   0  ||   0   1   2   0   2   1   1
  0   0   0   0   0   0   1  ||   1   1   2   2   2   1   0

Round 24:
  0   0   0   0   0   0   1  ||   0   0   0   0   0   2   0
  0   0   0   0   0   0   1  ||   0   0   0   0   0   2   0
  0   0  [0]  0   0   0   0  ||   1   1  [2]  2   2   1   1
  1   0   0   2   0   0   0  ||   0   1   2   0   2   1   1
  0   0   0   0   0   0   1  ||   1   1   2   2   2   1   0

Round 25:
  0   0   0   0   0  [0]  1  ||   0   0   0   0   0  [2]  0
  0   0   0   0   0   0   1  ||   0   0   0   0   0   2   0
  0   0   0   0   0   0   0  ||   1   1   1   1   1   1   1
  1   0   0   1   0   0   0  ||   0   1   1   0   1   1   1
  0   0   0   0   0   0   1  ||   1   1   1   1   1   1   0

Round 26:
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
 [0]  0   0   0   0   0   0  ||  [1]  1   1   1   1   0   0
  1   0   0   1   0   0   0  ||   0   1   1   0   1   1   1
  0   0   0   0   0   0   1  ||   1   1   1   1   1   1   0

Round 27:
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
  0   0  [0]  0   0   0   0  ||   0   0  [1]  1   1   0   0
  0   0   0   1   0   0   0  ||   0   0   1   0   1   1   1
  0   0   0   0   0   0   1  ||   0   0   1   1   1   1   0

Round 28:
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
  0   0   0   0   0   0   0  ||   0   0   0   0   0   0   0
  0   0   0   0   0  [0]  0  ||   0   0   0   0   0  [1]  1
  0   0   0   0   0   0   1  ||   0   0   0   0   0   1   0

Done in 28 rounds

1

इसे O (3 ^ (n)) गहराई के पेड़ का उपयोग करके हल किया जा सकता है। जहाँ n सभी वर्गों का योग है।

पहले विचार करें कि ओ (9 ^ n) के पेड़ के साथ समस्या को हल करना तुच्छ है, बस सभी संभावित बमबारी स्थानों पर विचार करें। एक उदाहरण के लिए अल्फ के कार्यान्वयन को देखें ।

अगला एहसास है कि हम नीचे से ऊपर बम बनाने के लिए काम कर सकते हैं और अभी भी एक न्यूनतम बमबारी पैटर्न प्राप्त कर सकते हैं।

  1. नीचे बाएं कोने से शुरू करें।
  2. केवल नाटकों के साथ विस्मरण करने के लिए इसे बम बनाएं जो समझ में आता है (ऊपर और दाईं ओर)।
  3. एक वर्ग को दाईं ओर ले जाएं।
  4. जबकि लक्ष्य का मूल्य शून्य से अधिक है, 2 नाटकों में से प्रत्येक पर विचार करें जो समझ में आता है (सीधे ऊपर या ऊपर और दाईं ओर), लक्ष्य के मूल्य को एक से कम करें, और प्रत्येक संभावना के लिए एक नई शाखा बनाएं।
  5. दूसरे को दाईं ओर ले जाएं।
  6. जबकि लक्ष्य का मूल्य शून्य से अधिक है, 3 में से प्रत्येक पर विचार करें जो समझ में आता है (बाएं, ऊपर और दाएं), एक से लक्ष्य के मूल्य को कम करें, और प्रत्येक संभावना के लिए एक नई शाखा बनाएं।
  7. पंक्ति समाप्त होने तक चरण 5 और 6 दोहराएं।
  8. एक पंक्ति ऊपर ले जाएँ और चरण 1 से 7 तक दोहराएं जब तक कि पहेली हल न हो जाए।

यह एल्गोरिथम सही है क्योंकि

  1. प्रत्येक बिंदु को किसी बिंदु पर पूरा करना आवश्यक है।
  2. एक पंक्ति को पूरा करने के लिए हमेशा एक या उससे ऊपर, एक नीचे या उस पंक्ति के भीतर एक नाटक की आवश्यकता होती है।
  3. पंक्ति पर या पंक्ति के नीचे एक नाटक की तुलना में सबसे कम अस्पष्ट पंक्ति के ऊपर किसी एक को चुनना हमेशा अच्छा या बेहतर होता है।

व्यवहार में यह एल्गोरिदम नियमित रूप से अपने सैद्धांतिक अधिकतम की तुलना में बेहतर करेगा क्योंकि यह नियमित रूप से पड़ोसियों पर बमबारी करेगा और खोज के आकार को कम करेगा। यदि हम मानते हैं कि प्रत्येक बमबारी में 4 अतिरिक्त लक्ष्यों का मूल्य घटता है, तो हमारा एल्गोरिथ्म ओ (3 ^ (n / 4)) या लगभग O (1.3 ^ n) में चलेगा।

क्योंकि यह एल्गोरिथ्म अभी भी घातीय है, इसलिए खोज की गहराई को सीमित करना बुद्धिमानी होगी। हम कुछ संख्याओं, X की अनुमति दी गई शाखाओं की संख्या को सीमित कर सकते हैं, और एक बार जब हम इस गहन होते हैं तो हम एल्गोरिथ्म को अब तक पहचाने गए सर्वोत्तम पथ को चुनने के लिए मजबूर करते हैं (जिसके पास अपने टर्मिनल पत्तों में न्यूनतम कुल बोर्ड योग है )। फिर हमारे एल्गोरिथ्म को ओ (3 ^ X) समय में चलाने की गारंटी है, लेकिन सही उत्तर प्राप्त करने की गारंटी नहीं है। हालांकि, हम हमेशा एक्स बढ़ा सकते हैं और अनुभवजन्य रूप से परीक्षण कर सकते हैं यदि बढ़ी हुई गणना और बेहतर उत्तर के बीच व्यापार बंद हो तो सार्थक है।


1

मूल्यांकन समारोह, कुल राशि:

int f (int ** matrix, int width, int height, int x, int y)
{
    int m[3][3] = { 0 };

    m[1][1] = matrix[x][y];
    if (x > 0) m[0][1] = matrix[x-1][y];
    if (x < width-1) m[2][1] = matrix[x+1][y];

    if (y > 0)
    {
        m[1][0] = matrix[x][y-1];
        if (x > 0) m[0][0] = matrix[x-1][y-1];
        if (x < width-1) m[2][0] = matrix[x+1][y-1];
    }

    if (y < height-1)
    {
        m[1][2] = matrix[x][y+1];
        if (x > 0) m[0][2] = matrix[x-1][y+1];
        if (x < width-1) m[2][2] = matrix[x+1][y+1];
    }

    return m[0][0]+m[0][1]+m[0][2]+m[1][0]+m[1][1]+m[1][2]+m[2][0]+m[2][1]+m[2][2];
}

उद्देश्य समारोह:

Point bestState (int ** matrix, int width, int height)
{
    Point p = new Point(0,0);
    int bestScore = 0;
    int b = 0;

    for (int i=0; i<width; i++)
        for (int j=0; j<height; j++)
        {
            b = f(matrix,width,height,i,j);

            if (b > bestScore)
            {
                bestScore = best;
                p = new Point(i,j);
            }
        }

    retunr p;
}

समारोह को नष्ट:

void destroy (int ** matrix, int width, int height, Point p)
{
    int x = p.x;
    int y = p.y;

    if(matrix[x][y] > 0) matrix[x][y]--;
    if (x > 0) if(matrix[x-1][y] > 0) matrix[x-1][y]--;
    if (x < width-1) if(matrix[x+1][y] > 0) matrix[x+1][y]--;

    if (y > 0)
    {
        if(matrix[x][y-1] > 0) matrix[x][y-1]--;
        if (x > 0) if(matrix[x-1][y-1] > 0) matrix[x-1][y-1]--;
        if (x < width-1) if(matrix[x+1][y-1] > 0) matrix[x+1][y-1]--;
    }

    if (y < height-1)
    {
        if(matrix[x][y] > 0) matrix[x][y+1]--;
        if (x > 0) if(matrix[x-1][y+1] > 0) matrix[x-1][y+1]--;
        if (x < width-1) if(matrix[x+1][y+1] > 0) matrix[x+1][y+1]--;
    }
}

लक्ष्य समारोह:

bool isGoal (int ** matrix, int width, int height)
{
    for (int i=0; i<width; i++)
        for (int j=0; j<height; j++)
            if (matrix[i][j] > 0)
                return false;
    return true;
}

रैखिक अधिकतमकरण समारोह:

void solve (int ** matrix, int width, int height)
{
    while (!isGoal(matrix,width,height))
    {
        destroy(matrix,width,height, bestState(matrix,width,height));
    }
}

यह इष्टतम नहीं है, लेकिन एक बेहतर मूल्यांकन फ़ंक्शन खोजने के माध्यम से अनुकूलित किया जा सकता है।

.. लेकिन इस समस्या के बारे में सोचते हुए, मैं सोच रहा था कि मुख्य मुद्दों में से एक शून्य के बीच में कुछ बिंदुओं पर छोड़ दिए गए आंकड़े हैं, इसलिए मैं एक और दृष्टिकोण लूंगा .. जो शून्य में न्यूनतम मूल्यों पर हावी है, फिर प्रयास करें संभव के रूप में शून्य से बच, जो न्यूनतम मौजूदा मूल्य (एस) या तो के सामान्य न्यूनतम करने के लिए नेतृत्व


0

यह सारी समस्या एक दूरी को संपादित करने के लिए उबलती है। बस दिए गए मैट्रिक्स और शून्य मैट्रिक्स के बीच लेवेंसहाइट दूरी के एक संस्करण की गणना करें, जहां मध्यवर्ती सरणियों के बीच की दूरी को स्टोर करने के लिए डायनामिक प्रोग्रामिंग का उपयोग करके बम को बम से बदल दिया जाता है। मैं एक कुंजी के रूप में मैट्रिस के हैश का उपयोग करने का सुझाव देता हूं। छद्म-पायथन में:

memo = {}

def bomb(matrix,i,j):
    # bomb matrix at i,j

def bombsRequired(matrix,i,j):
    # bombs required to zero matrix[i,j]

def distance(m1, i, len1, m2, j, len2):
    key = hash(m1)
    if memo[key] != None: 
        return memo[key]

    if len1 == 0: return len2
    if len2 == 0: return len1

    cost = 0
    if m1 != m2: cost = m1[i,j]
    m = bomb(m1,i,j)
    dist = distance(str1,i+1,len1-1,str2,j+1,len2-1)+cost)
    memo[key] = dist
    return dist

0

यह पहले पूछे गए प्रश्न का उत्तर था। मैंने ध्यान नहीं दिया कि उसने मापदंडों को बदल दिया है।

सभी लक्ष्यों की एक सूची बनाएँ। एक बूंद (स्वयं और सभी पड़ोसियों) से प्रभावित सकारात्मक मूल्यों की संख्या के आधार पर लक्ष्य के लिए एक मूल्य प्रदान करें। उच्चतम मूल्य एक नौ होगा।

प्रत्येक लक्षित लक्ष्य के योग पर द्वितीयक अवरोही क्रम के साथ प्रभावित (अवरोही) लक्ष्यों की संख्या द्वारा लक्ष्यों को क्रमबद्ध करें।

उच्चतम रैंक वाले लक्ष्य पर बम गिराएं, फिर लक्ष्यों की गणना करें और तब तक दोहराएं जब तक कि सभी लक्ष्य मान शून्य न हों।

सहमत, यह हमेशा सबसे इष्टतम नहीं है। उदाहरण के लिए,

100011
011100
011100
011100
000000
100011

यह दृष्टिकोण स्पष्ट करने के लिए 5 बम ले जाएगा। वैकल्पिक रूप से, हालांकि, आप इसे 4 में कर सकते हैं। फिर भी, बहुत करीब है और कोई पीछे नहीं है। अधिकांश स्थितियों के लिए यह इष्टतम होगा, या बहुत करीब होगा।

मूल समस्या संख्याओं का उपयोग करते हुए, यह दृष्टिकोण 28 बमों में हल करता है।

इस दृष्टिकोण को प्रदर्शित करने के लिए कोड जोड़ना (बटन के साथ फ़ॉर्म का उपयोग करना):

         private void button1_Click(object sender, EventArgs e)
    {
        int[,] matrix = new int[10, 10] {{5, 20, 7, 1, 9, 8, 19, 16, 11, 3}, 
                                         {17, 8, 15, 17, 12, 4, 5, 16, 8, 18},
                                         { 4, 19, 12, 11, 9, 7, 4, 15, 14, 6},
                                         { 17, 20, 4, 9, 19, 8, 17, 2, 10, 8},
                                         { 3, 9, 10, 13, 8, 9, 12, 12, 6, 18}, 
                                         {16, 16, 2, 10, 7, 12, 17, 11, 4, 15},
                                         { 11, 1, 15, 1, 5, 11, 3, 12, 8, 3},
                                         { 7, 11, 16, 19, 17, 11, 20, 2, 5, 19},
                                         { 5, 18, 2, 17, 7, 14, 19, 11, 1, 6},
                                         { 13, 20, 8, 4, 15, 10, 19, 5, 11, 12}};


        int value = 0;
        List<Target> Targets = GetTargets(matrix);
        while (Targets.Count > 0)
        {
            BombTarget(ref matrix, Targets[0]);
            value += 1;
            Targets = GetTargets(matrix);
        }
        Console.WriteLine( value);
        MessageBox.Show("done: " + value);
    }

    private static void BombTarget(ref int[,] matrix, Target t)
    {
        for (int a = t.x - 1; a <= t.x + 1; a++)
        {
            for (int b = t.y - 1; b <= t.y + 1; b++)
            {
                if (a >= 0 && a <= matrix.GetUpperBound(0))
                {
                    if (b >= 0 && b <= matrix.GetUpperBound(1))
                    {
                        if (matrix[a, b] > 0)
                        {
                            matrix[a, b] -= 1;
                        }
                    }
                }
            }
        }
        Console.WriteLine("Dropped bomb on " + t.x + "," + t.y);
    }

    private static List<Target> GetTargets(int[,] matrix)
    {
        List<Target> Targets = new List<Target>();
        int width = matrix.GetUpperBound(0);
        int height = matrix.GetUpperBound(1);
        for (int x = 0; x <= width; x++)
        {
            for (int y = 0; y <= height; y++)
            {
                Target t = new Target();
                t.x = x;
                t.y = y;
                SetTargetValue(matrix, ref t);
                if (t.value > 0) Targets.Add(t);
            }
        }
        Targets = Targets.OrderByDescending(x => x.value).ThenByDescending( x => x.sum).ToList();
        return Targets;
    }

    private static void SetTargetValue(int[,] matrix, ref Target t)
    {
        for (int a = t.x - 1; a <= t.x + 1; a++)
        {
            for (int b = t.y - 1; b <= t.y + 1; b++)
            {
                if (a >= 0 && a <= matrix.GetUpperBound(0))
                {
                    if (b >= 0 && b <= matrix.GetUpperBound(1))
                    {
                        if (matrix[ a, b] > 0)
                        {
                            t.value += 1;
                            t.sum += matrix[a,b];
                        }

                    }
                }
            }
        }

    }

एक वर्ग जिसकी आपको आवश्यकता होगी:

        class Target
    {
        public int value;
        public int sum;
        public int x;
        public int y;
    }

1
इष्टतम नहीं है। काउंटरएक्सप्लिमेंट: 09090इस दृष्टिकोण के लिए 18 बमों की आवश्यकता होती है यह 9 में किया जा सकता है
18

@ मूल आपने उत्तर को पूरी तरह से नहीं पढ़ा है। चूंकि यह गैर-शून्य क्षेत्रों की संख्या पर आधारित है, इसलिए यह एल्गोरिथ्म मध्य शून्य पर बमबारी करेगा और 9 बूंदों में किया जाएगा। 9 का उच्च मूल्य है क्योंकि आठ पड़ोसी और खुद तक हैं।
एंथनी क्वीन

तो फिर कैसे के बारे में 1010101, 0010100?
मिस्टिकल

@ मिस्टिक पहले, पहले शून्य, फिर अंतिम शून्य हिट होगा। यह दो बूंद होगी। ऐसा इसलिए है क्योंकि हर बार जब यह बम गिरता है, तो यह अगले सबसे अच्छे लक्ष्य को पुन: प्राप्त करता है। अंतिम उदाहरण के लिए, मध्य शून्य फिर से; एक बूंद।
एंथनी क्वीन

1
@AnthonyQueen: यह काम नहीं करता है। कृपया मेरे प्रतिरूप के लिए chat.stackoverflow.com/transcript/message/8224273#8224273 देखें ।
nnonneo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.