2013-04-13 12 views
10

के संयोजन के लिए निकटतम मूल्य प्राप्त करें मैं एक एल्गोरिदम खोज रहा हूं जिसे मैं "अन्य मान" के रूप में जितना संभव हो सके, सरणी में मानों को संयोजित करने के लिए उपयोग कर सकता हूं।किसी सरणी (जेएस)

उदाहरण के लिए, मैं यह जानना चाहता हूं कि बंद करने का परिणाम क्या संयोजन है जो 2.5 है। और मेरी सरणी [0.5, 1.0, 1.5, 2.0, 3.0] है। इस मामले में संयोजन 2.0+0.5 होगा।

2.7 एक ही कॉम्बो (2.5 निकटतम) उत्पन्न करेगा, जबकि 3.7 3.0+0.5 और 7.0 3.0+3.0+1.0 होगा।

मैं उपलब्ध संयोजन बनाने के लिए विभिन्न एल्गोरिदम पर पढ़ रहा हूं और उदाहरण के लिए - उदाहरण के लिए, यह एक: https://codereview.stackexchange.com/questions/7001/better-way-to-generate-all-combinations हालांकि, मुझे एक ऐसा फ़ंक्शन लिखने में कठिनाई हो रही है जो एक ही मान को कई बार उपयोग करने की अनुमति देता है (जैसे 7.0 के साथ मेरा उदाहरण)। इससे संयोजनों की संख्या काफी बड़ी हो जाती है।

कोई भी व्यक्ति जो अच्छा उदाहरण ले रहा है उसे दूर कर दिया गया है? या देने के लिए कोई संकेतक है?

EDIT @zkar ने मुझे "knapsack समस्या" के बारे में बताया। मैं इसे अपने उदाहरण के लिए जोड़ सकता हूं, मांग किए गए मान एक निर्दिष्ट सीमा (1.0 और 10.0) में हैं - जो कुछ हद तक संयोजन को सीमित करता है।

+2

इस [नेप्सेक समस्या] पर देखो (http://en.wikipedia.org/wiki/Knapsack_problem) लगता है मुझे यह है कि आपको यही पढ़ना चाहिए। – zkar

+1

जबकि मैं मानता हूं कि यह "नॅपैकैक समस्या" के अंतर्गत आ सकता है, फिर भी इसमें अंतर है कि मेरे पास चिंता करने के लिए केवल एक प्रकार का मूल्य है (चलो विकिपीडिया-उदाहरण में वजन कहें), दो नहीं। – Marcus

+0

यदि आप सरणी में सबसे नज़दीक खोजना चाहते हैं तो आप इसे क्रमबद्ध करने से संख्या को पुश कर सकते हैं और फिर उस नंबर की दूसरी और पिछली संख्या लें और गणित का उपयोग करने का प्रयास करें।दौर या इस तरह कुछ कोशिश करें;) – Givi

उत्तर

1

आपकी समस्या Coin Problem का एक मिश्रण और Knapsack Problem

है सिक्के केवल एक बार उपयोग किया जाता है:

मूल्यों एस का एक सेट को देखते हुए, एन = | एस |, मी: मूल्य

अनुमान लगाने के लिए
DEFINE BEST = { } 
DEFINE SUM = 0 
DEFINE K = 0 

WHILE S IS NOT EMPTY DO 
    K = K + 1 
    FIND MIN { Si : |(SUM+Si) - m| is minimal } 
    ADD TUPLE < Si, |(SUM+Si) - m|, K > to BEST 
    SUM = SUM + Si 
    REMOVE Si from S 
END-FOR 

RETURN BEST 

इस एल्गोरिथ्म समय में चलता है: हे (| S |) ~ O (n)

सेट सबसे अच्छा होगा n समाधान, प्रत्येक कश्मीर के लिए: 1..n

कश्मीर के लिए

:

GIVEN BEST = { < COIN:X, DISTANCE:Y, DEGREE:K > } 
DEFINE SOLUTION = { } 
Y" = MINIMUM Y IN BESTi.Y for i: 1..n 
KEEP ADDING BESTj.X to SOLUTION UNTILL BESTj.Y = Y" FOR j: 1..n 
: आप पूरा समाधान खोजने के लिए कि मंच

पर इष्टतम विकल्प नहीं है

सिक्के किया जा सकता है फिर से इस्तेमाल किया:

DEFINE SOLUTION = { } 
DEFINE SUM = 0 
LESS = { Si : Si < m } 
SORT LESS IN DESCENDING ORDER 
FOR Li in LESS DO 
    WHILE (SUM+Li) <= m DO 
     SUM = SUM + Li 
     ADD Li TO SOLUTION 
    END-WHILE 

    IF SUM = m THEN BREAK-FOR 
END-FOR 
RETURN SOLUTION 

में जावास्क्रिप्ट:

function coinProblem (var coins, var value) 
{ 
    var solution = new Array(); 
    var sum = 0; 
    var less = new Array(); 

    for (var i in coins) 
     if (i <= value) 
      less.push(i); 

    // sort in descending order 
    less.sort(); 
    less.reverse(); 

    for (var i in less) 
    { 
     while ((sum+i) <= value) 
     { 
      solution.push(i); 
      sum = sum + i; 
     } 

     if (sum == value) break; 
    } 

    return solution; 
} 
+0

मैं पूरी तरह से अपने छद्म कोड सम्मेलनों को गड़बड़ नहीं करता हूं, विशेष रूप से, लाइन को कैसे ढूंढना चाहिए {FIND MIN {Si: | (SUM + Si) - m | न्यूनतम है} 'पढ़ा जा सकता है? – RBarryYoung

+0

हम्म, अगर मैं इसे सही ढंग से पढ़ता हूं, तो क्या यह सिर्फ लालची ह्युरिस्टिक नहीं है? यह जरूरी नहीं है कि हर समय सटीक उत्तर वापस आएगा? – RBarryYoung

+0

फेडेसोव के समाधान के साथ, यदि मैं 'एस = {0.4,1.0}, एम = 0.8' पास करता हूं तो मुझे लगता है कि आपका एल्गोरिदम सही' {0.4,0.4} 'के बजाय' {1.0} 'देता है। – RBarryYoung

1

आप इस सरल एल्गोरिथ्म (JSFiddle demo) की कोशिश कर सकते हैं:

/** 
* @param src {Array} List of available values 
* @param val {Number} Target value 
* @returns {Array} 
*/ 
function get_combinations(src, val) 
{ 
    var result = []; 
    var source = src.slice(); 
    source.sort(); 

    while (val > 0) 
    { 
     for (var i = source.length - 1; i >= 0; i--) 
     { 
      if (source[i] <= val || i == 0) 
      { 
       val = val - source[i]; 
       result.push(source[i]); 
       break; 
      } 
     } 
    } 

    return result; 
} 
+0

को अधिकतम करने के लिए पैरामीटर 'src = {0.4,1.0}, val = 0.8' वापसी का जवाब' {0.4,0.4} 'होना चाहिए, लेकिन ऐसा लगता है कि यह एल्गोरिदम इसके बजाए '{1.0}' लौटाता है। – RBarryYoung

+0

कुछ और परीक्षण चलाने के बाद, मुझे कुछ मामलों में कुछ अजीब परिणाम मिल रहे हैं। उदाहरण के लिए 'src = [0.5, 1.0, 1.25, 1.5, 2.0, 3.0] 'और' val = 1.44' के साथ' परिणाम = [1.5] 'देना चाहिए। इसके बजाय मुझे 'परिणाम = [1.25, 0.5] 'मिलता है। यह निश्चित रूप से मुश्किल है =) @khaleds समाधान को देखकर यह देखने के लिए कि क्या मैं इसे कुछ में लागू कर सकता हूं। – Marcus

संबंधित मुद्दे