फ़ेलिक्स सही है कि यह knapsack समस्या का एक विशेष मामला है। उनके गतिशील प्रोग्रामिंग एल्गोरिदम ओ (के * एम) आकार और ओ (के * के * एम) समय की मात्रा लेता है। मेरा मानना है कि वेरिएबल एन का उपयोग वास्तव में के।
नापसंद समस्या के लिए समर्पित दो पुस्तकें हैं। केलेरर, पर्सची और पिसिंगर [2004, स्प्रिंगर-वेरलाग, आईएसबीएन 3-540-40286-1] द्वारा नवीनतम पृष्ठ, उनके पृष्ठ 76 पर एक बेहतर गतिशील प्रोग्रामिंग एल्गोरिदम प्रदान करता है, चित्रा 4.2 जो ओ (के + एम) स्पेस लेता है और ओ (केएम) समय, जो फ़ेलिक्स द्वारा दिए गए गतिशील प्रोग्रामिंग एल्गोरिदम की तुलना में भारी कमी है। ध्यान दें कि पुस्तक की एल्गोरिदम की अंतिम पंक्ति पर एक टाइपो है जहां यह सी-बार होना चाहिए: = सी-बार - w_ (आर (सी-बार))।
मेरा सी # कार्यान्वयन नीचे है। मैं यह नहीं कह सकता कि मैंने इसका व्यापक परीक्षण किया है, और मैं इस पर प्रतिक्रिया का स्वागत करता हूं। मैंने पुस्तक में एल्गोरिदम में दिए गए सेट की अवधारणा को लागू करने के लिए BitArray
का उपयोग किया था। मेरे कोड में, c
क्षमता है (जो मूल पोस्ट में एम कहा जाता था), और मैंने वजन रखने वाले सरणी के रूप में A
के बजाय w
का उपयोग किया।
इसके उपयोग का एक उदाहरण है:
int[] optimal_indexes_for_ssp = new SubsetSumProblem(12, new List<int> { 1, 3, 5, 6 }).SolveSubsetSumProblem();
जहां सरणी optimal_indexes_for_ssp
शामिल हैं [0,2,3] तत्वों 1, 5, 6.
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
public class SubsetSumProblem
{
private int[] w;
private int c;
public SubsetSumProblem(int c, IEnumerable<int> w)
{
if (c < 0) throw new ArgumentOutOfRangeException("Capacity for subset sum problem must be at least 0, but input was: " + c.ToString());
int n = w.Count();
this.w = new int[n];
this.c = c;
IEnumerator<int> pwi = w.GetEnumerator();
pwi.MoveNext();
for (int i = 0; i < n; i++, pwi.MoveNext())
this.w[i] = pwi.Current;
}
public int[] SolveSubsetSumProblem()
{
int n = w.Length;
int[] r = new int[c+1];
BitArray R = new BitArray(c+1);
R[0] = true;
BitArray Rp = new BitArray(c+1);
for (int d =0; d<=c ; d++) r[d] = 0;
for (int j = 0; j < n; j++)
{
Rp.SetAll(false);
for (int k = 0; k <= c; k++)
if (R[k] && k + w[j] <= c) Rp[k + w[j]] = true;
for (int k = w[j]; k <= c; k++) // since Rp[k]=false for k<w[j]
if (Rp[k])
{
if (!R[k]) r[k] = j;
R[k] = true;
}
}
int capacity_used= 0;
for(int d=c; d>=0; d--)
if (R[d])
{
capacity_used = d;
break;
}
List<int> result = new List<int>();
while (capacity_used > 0)
{
result.Add(r[capacity_used]);
capacity_used -= w[r[capacity_used]];
} ;
if (capacity_used < 0) throw new Exception("Subset sum program has an internal logic error");
return result.ToArray();
}
}
स्रोत
2013-08-30 14:26:58
मैं नहीं पा रहा हूँ करने के लिए इसी अपने प्रश्न को समझने के लिए, क्या आप यहां एक उदाहरण प्रदान कर सकते हैं। यहां मैं समझता हूं, [3,5,2,6,1,8,15,18,4] यदि के 3 एम 15 है तो मैं 8,2,4 का चयन कर सकता हूं, क्या यह जवाब होना चाहिए? – AKS
@AKS प्रश्न है ... हम केवल के लम्बा सबसेट बना सकते हैं ... और इन के लंबाई लंबाई से बाहर जो सबसेट अधिकतम योग देता है ... इस शर्त के अधीन कि राशि एम – Shivendra
से कम है, ठीक है उदाहरण मैंने दिया है, यदि के 3 है तो लंबाई 3 के सभी सबसेट्स में से अधिकतम राशि है लेकिन 15 से कम है। धन्यवाद !! – AKS