तत्वों के पुनरावृत्ति के बिना जोड़े के एक सेट से संयोजन उत्पन्न करना


28

मेरे पास जोड़े का एक सेट है। प्रत्येक जोड़ी फॉर्म (x, y) की है जैसे कि x, y सीमा से पूर्णांक के हैं [0,n)

तो, यदि n 4 है, तो मेरे पास निम्नलिखित जोड़े हैं:

(0,1) (0,2) (0,3)
(1,2) (1,3) 
(2,3) 

मेरे पास पहले से ही जोड़े हैं। अब, मुझे n/2जोड़ों का उपयोग करके एक संयोजन का निर्माण करना होगा, ताकि किसी भी पूर्णांक को दोहराया न जाए (दूसरे शब्दों में, प्रत्येक पूर्णांक कम से कम एक बार अंतिम संयोजन में प्रकट होता है)। बेहतर समझ के लिए सही और गलत संयोजन के उदाहरण निम्नलिखित हैं

 1. (0,1)(1,2) [Invalid as 3 does not occur anywhere]
 2. (0,2)(1,3) [Correct]
 3. (1,3)(0,2) [Same as 2]

क्या कोई मेरे पास सभी संभावित संयोजनों को उत्पन्न करने का एक तरीका सुझा सकता है, जब मेरे पास जोड़े होंगे।


शायद अपने जोड़े का प्रतिनिधित्व करने के लिए 2d सरणी का उपयोग करके। मान्य संयोजन एन सरणी कोशिकाओं के चयन के अनुरूप हैं, जिसमें प्रत्येक पंक्ति और स्तंभ में ठीक 1 चयनित सेल होता है।
जो

4
क्या आप कह रहे हैं कि इनपुट सभी जोड़े का सेट है ? यदि ऐसा है, तो आपको बस यह कहना चाहिए कि इनपुट केवल । n
rgrig

2
क्या हमेशा भी है? यदि नहीं, तो बयान "कोई भी पूर्णांक दोहराया नहीं जाता है" और "प्रत्येक पूर्णांक कम से कम एक बार अंतिम संयोजन में प्रकट होता है" विरोधाभासी हैं। n
दिमित्रो कोर्डुबन

1
@rgrig के रूप में एक ही समस्या: इनपुट सभी अनियंत्रित जोड़े है या क्या यह संभावित जोड़े का एक मनमाना सेट है? यदि यह सभी जोड़े हैं तो आप बस कह सकते हैं इनपुट , सूची देने की कोई आवश्यकता नहीं है। n
केव

1
आप अपनी जोड़ी के प्रारंभिक सेट द्वारा परिभाषित बिंदुओं पर ग्राफ के सभी सही मिलान उत्पन्न करने में रुचि रखते हैं । इसके अलावा ऐसा लगता है कि आप उन बिंदुओं पर पूरा ग्राफ बनने के लिए उस ग्राफ को लेते हैं। यदि आप इसका उल्लेख करते हैं तो आपका प्रश्न स्पष्ट हो जाएगा। वहाँ हैं अन्य मिलान। ( n - 1 ) ! ! : = 1 × 3 × 5 × × ( n - 1 )n(n1)!!:=1×3×5××(n1)
मार्क वैन लीउवेन

जवाबों:


14

एक सीधा तरीका एक पुनरावर्ती प्रक्रिया है जो प्रत्येक आह्वान पर निम्नलिखित कार्य करता है। प्रक्रिया का इनपुट जोड़े की एक सूची है जो पहले से ही चुनी गई है और सभी जोड़े की सूची है।

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

इस एल्गोरिथ्म की कल्पना करने का तरीका एक पेड़ के साथ है, जिसके रास्ते गैर-अतिव्यापी जोड़े के अनुक्रम हैं। पेड़ के पहले स्तर में सभी जोड़े होते हैं जिनमें 0. होते हैं। ऊपर के उदाहरण के लिए, पेड़ है

           जड़
             |
     ----------------
     | | |
   (0,1) (0,2) (0,3)
     | | |
   (2,3) (1,3) (1,2)

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

इस प्रकार के खोज एल्गोरिदम को किसी विशेष प्रकार की सभी वस्तुओं की गणना की कई समान समस्याओं के लिए विकसित किया जा सकता है।


यह सुझाव दिया गया था कि शायद ओपी का मतलब था कि सभी जोड़े इनपुट में हैं, न कि उनमें से केवल एक सेट जैसा कि सवाल कहता है। उस स्थिति में एल्गोरिथ्म बहुत आसान है क्योंकि यह जांचना आवश्यक नहीं है कि कौन से जोड़े की अनुमति है। सभी जोड़े के सेट को उत्पन्न करना भी आवश्यक नहीं है; निम्नलिखित pseudocode वही करेगा जो ओपी ने पूछा था। यहाँ इनपुट संख्या है, "सूची" एक खाली सूची के रूप में शुरू होती है, और "कवर" 0. के लिए प्रारंभ की गई लंबाई की एक सरणी है। इसे कुछ और अधिक कुशल बनाया जा सकता है लेकिन यह मेरा तत्काल लक्ष्य नहीं है।nnn

sub cover {
  i = 0;
  while ( (i < n) && (covered[i] == 1 )) {
   i++;
  }
  if ( i == n ) { print list; return;}
  covered[i] = 1;
  for ( j = 0; j < n; j++ ) {
    if ( covered[j] == 0 ) {
      covered[j] = 1;
      push list, [i,j];
      cover();
      pop list;
      covered[j] = 0;
    }
  }
  covered[i] = 0;
}

यह काम करना चाहिए, लेकिन यह शायद ऐसा करने का सबसे कुशल तरीका नहीं है।
जो

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

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

10

Sn[0,n)Sn+2Snn

def pairs(n):
    if (n%2==1 or n<2):
        print("no solution")
        return
    if (n==2):
        yield(  [[0,1]]  )
    else:
        Sn_2 = pairs(n-2) 
        for s in Sn_2:
            yield( s + [[n-2,n-1]] )
            for i in range(n/2-1):
                sn = list(s)
                sn.remove(s[i])
                yield( sn + [ [s[i][0], n-2] , [s[i][1], n-1] ] )
                yield( sn + [ [s[i][1], n-2] , [s[i][0], n-1] ] )

आप कॉल करके सभी जोड़ों को सूचीबद्ध कर सकते हैं

for x in pairs(6):
   print(x)

6

अद्यतन : मेरा पहले वाला उत्तर द्विदलीय रेखांकन के साथ था, जिसके बारे में ओपी नहीं पूछ रहा था। संबंधित जानकारी के रूप में मैं इसे अभी के लिए छोड़ रहा हूं। लेकिन अधिक प्रासंगिक जानकारी nonbipartite रेखांकन में सही मिलान से संबंधित है।

इस संबंध में, Propp द्वारा एक अच्छा सर्वेक्षण है जो प्रगति को रेखांकित करता है (1999 तक)। उस लेख में कुछ विचार और संबंधित लिंक उपयोगी साबित हो सकते हैं। TL; DR है - यह मुश्किल है :)

--- पुराने उत्तर की शुरुआत

ध्यान दें कि आप जो करने के लिए कह रहे हैं, वह एक द्विदलीय ग्राफ पर सभी संभव परिपूर्ण मिलानों की गणना करना है। ऐसा करने के लिए कई अलग-अलग एल्गोरिदम हैं, और विशेष रूप से हाल ही में एक आईएसएएसी 2001 से है

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


द्विदलीय ग्राफ में दिए गए लेबल के साथ दो सेट होते हैं [0, n), और एक किनारा है (i, j) यदि और केवल अगर (i! = J)
जो

nKn

2
स्थायी उत्तर की गणना करता है। लेकिन ओपी उन्हें कहना चाहता है
सुरेश

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

4

आपके द्वारा चुनी गई प्रत्येक जोड़ी दो पंक्तियों को समाप्त करती है जिससे आप अब और नहीं उठा सकते हैं। इस विचार का उपयोग एक पुनरावर्ती एल्गोरिथ्म को स्थापित करने के लिए किया जा सकता है (स्काला में):

def combine(pairs : Seq[(Int,Int)]) : Seq[Seq[(Int, Int)]] = pairs match {
  case Seq() => Seq()
  case Seq(p) => Seq(Seq(p))
  case _ => {
    val combinations = pairs map { case (a,b) => {
      val others = combine(pairs filter { case (c,d) =>
        a != c && a != d && b != c && b != d
      })

      others map { s => ((a,b) +: s) }
    }}

    combinations.flatten map { _.sorted } distinct
  }
}

यह निश्चित रूप से अधिक कुशल तरीके से व्यक्त किया जा सकता है। विशेष रूप से, संयोजन के लिए पूरी पंक्तियों पर विचार नहीं करने का विचार कॉल द्वारा उपयोग नहीं किया गया है filter


क्या यह संयोजन भी नहीं लौटाएगा जिसमें हर संख्या शामिल नहीं है, लेकिन जिसे बढ़ाया नहीं जा सकता क्योंकि मूल अनुक्रम में ऐसे जोड़े नहीं हैं जो उनका विस्तार कर सकें? यदि हां, तो उन संयोजनों को फ़िल्टर करने की आवश्यकता है।
कार्ल मम्मर्ट

n2N

(0,1)n=4

हाँ। लेकिन जैसा कि मैंने कहा, मेरा जवाब ओपी के प्रस्ताव के परिदृश्य से संबंधित है, न कि मनमाना इनपुट।
राफेल

जैसा कि मैंने मूल प्रश्न पढ़ा, यह जोड़ों के एक मनमाने सेट के बारे में है, ओपी कभी नहीं कहता कि सभी जोड़े संभव हैं। लेकिन मैं मानता हूं कि ओपी इस बारे में अधिक स्पष्ट हो सकता है।
कार्ल मम्मर्ट

4

जबकि प्रश्न के लिए पहले से ही कई प्यारे ऐनर हैं, मुझे लगता है कि उनके पीछे मूल, सामान्य, चाल को इंगित करना अच्छा होगा।

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

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

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


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.