Алгоритм оптимизации Java - PullRequest
       31

Алгоритм оптимизации Java

5 голосов
/ 11 октября 2019

Я новичок в программировании, в настоящее время я сталкиваюсь с проблемой создания алгоритма оптимизации, я не могу найти хорошее и эффективное решение для достижения того, чего я ожидаю от моего текущего сценария столкновения. Это тот случай:

Предположим, что сейчас у Джеймса 900 долларов, а в магазине 4 предмета по разной цене.

предмет A: 450 баксов

предметB: 300 баксов

элемент C: 350 баксов

элемент D: 200 баксов

* количество на складе каждого элемента одно.

Теперь Джеймсу нужно максимально использовать свои текущие деньги (900 баксов). Другими словами, он может покупать любые предметы, но оставшиеся деньги должны быть как можно меньше. В этом случае лучшим результатом будет: Джеймс принес предметы B, C и D, его оставшийся баланс составит 50 баксов.

Это легко объяснить словом, но когда придете в программу или напишите алгоритм дляв этом случае это совсем другая история.

Я пытался написать логику: отсортировать цену товара от низкой до высокой, затем вычесть денежный баланс 900 баксов из товара с наименьшей ценой, пока не будет куплен товар, который можно купить на балансе. Но я понял, что эта логика не в состоянии добиться максимального использования денег. Например, когда сумма в 900 баксов изменяется на 800 баксов, лучшим вариантом является покупка товара на 450 и 350 баксов, где оставшееся будет равно нулю, но моя логика будет покупать товары на 300 и 200 баксов из-за ранней сортировки товаров. ,

Таким образом, я задаю этот вопрос здесь, чтобы найти какое-либо решение для обработки этого сценария. Я знаю, что это может быть глупым вопросом, но я действительно стараюсь изо всех сил учиться и совершенствоваться.

Алгоритм должен:

  • Способен обрабатывать гибкое количество товаров в магазине (только необязательно 4 предмета, может быть больше или меньше 4) и изменяемый начальный бюджет (необязательно)900 баксов, его можно менять каждый раз).
  • Каждый товар можно приобрести только один раз.

* Пожалуйста, предоставьте мне ссылку, чтобы узнать из вашего решения. Спасибо.

Ответы [ 3 ]

3 голосов
/ 18 октября 2019

Для тех, кто следит за этим вопросом, я нашел решение этого вопроса:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Map.Entry;
import java.util.LinkedHashMap;
import java.util.Iterator;

public class SumSet {
    static Map<Integer, ArrayList<Integer>> handleAllSumPossibilities(ArrayList<Integer> itemList, int balance, ArrayList<Integer> combination, Map<Integer, ArrayList<Integer>> qualifyItemsCombination) {

        System.out.println("COMBINATION FOR TEST: "+combination);

       int sum = 0; 
       Integer remain=null; 


       for (int x: combination){ sum += x;}; 

       if (sum <= balance && sum != 0){
            remain=(balance - sum);

            qualifyItemsCombination.put(remain,combination);
            System.out.println("ADD COMBINATION TO MAP: "+combination+"  CURRENT QUALIFIED COMBINATION: "+qualifyItemsCombination);
       }else{
            System.out.println("IGNORE COMBINATION: "+combination+"  NOT QUALIFY, THE COMBINATION IS EXCEEDED THE BALANCE");
       }
            System.out.println("_____________________________");


       for(int i=0;i<itemList.size();i++) {
             ArrayList<Integer> remainingItems = new ArrayList<Integer>();

             int pointingItem = itemList.get(i); 
             for (int j=i+1; j<itemList.size();j++) remainingItems.add(itemList.get(j));

             ArrayList<Integer> combinationRecord = new ArrayList<Integer>(combination);

             combinationRecord.add(pointingItem);

             Map<Integer, ArrayList<Integer>> retrievedItemsCombination = handleAllSumPossibilities( remainingItems, balance, combinationRecord, qualifyItemsCombination);
             qualifyItemsCombination = retrievedItemsCombination;

       }
            return qualifyItemsCombination;
    }



    static Map<Integer, ArrayList<Integer>> findBestCombination(ArrayList<Integer> itemList, int balance) {

        Map<Integer, ArrayList<Integer>> qualifyItemsCombination;
        qualifyItemsCombination = handleAllSumPossibilities(itemList,balance,new ArrayList<Integer>(),new HashMap<>());

        System.out.println("THE FINAL QUALIFIED COMBINATION: "+qualifyItemsCombination);

        //sort the key (remaining balance)
        List<Entry< Integer, ArrayList<Integer>>> qualifyItemsCombinationList = new ArrayList<>(qualifyItemsCombination.entrySet());
        qualifyItemsCombinationList.sort(Entry.comparingByKey());

        //place the sort result
        Map<Integer, ArrayList<Integer>> sortedResult = new LinkedHashMap<>();
        for (Entry<Integer, ArrayList<Integer>> entry : qualifyItemsCombinationList) {
            sortedResult.put(entry.getKey(), entry.getValue());
        }
        System.out.println("QUALIFIED COMBINATION AFTER SORTED: "+sortedResult);

        //iterate to get the first combination = the combination with lesser remaining.
        Map.Entry<Integer, ArrayList<Integer>> entry = sortedResult.entrySet().iterator().next();
        Integer getMapKey = entry.getKey();
        ArrayList<Integer> getMapValue=entry.getValue();

        //remove all the combination that contains the remaining(key)
        //different to the lesser remaining
        //the reason of doing this is to filter the combinations and ensure the map only left the combinations with the lesser remaining
        //since it might contains more than one combination are having the lesser remaining
        sortedResult.entrySet().removeIf(key -> key.getKey() != getMapKey);
        System.out.println("THE COMBINATION WITH LESSER BALANCE: "+sortedResult);

        return sortedResult;
    }



    public static void main(String args[]) {
        ArrayList<Integer> itemList = new ArrayList<>();
        itemList.add(450);
        itemList.add(350);
        itemList.add(300);
        itemList.add(200);

        int balance = 900;

        Map<Integer, ArrayList<Integer>> returnResult;
        returnResult = findBestCombination(itemList,balance);

        //Iterate to display all the combination with lesser balance remaining
        Iterator it = returnResult.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            System.out.println("THE LESSER REMAINING: "+pair.getKey() + ", THE COMBINATION TO ACHIVE THIS: " + pair.getValue());   
            it.remove(); // avoid concurrent modification exception
        }
    }
}

*** Скопируйте код и попробуйте его на онлайн-компиляторе Java:

https://www.jdoodle.com/online-java-compiler/

https://www.tutorialspoint.com/compile_java_online.php

*** Исправьте или исправьте мой ответ, если вы нашли какую-либо проблему или лучший способ максимизировать эффективность доставки данных. Спасибо.

0 голосов
/ 25 октября 2019

Вы можете решить задачу с помощью рекурсии. Если у вас есть метод, который может выбрать наилучшую комбинацию элементов для данного бюджета, реализуйте его следующим образом:

Выполните итерации по элементам и для каждого элемента, проверьте, находится ли он в рамках бюджета, и, если это так, удалитеэто из имеющихся предметов и вычесть его расходы из бюджета. Затем попросите рекурсивно найти наилучшее сочетание оставшихся предметов с оставшимся бюджетом и объединить его с текущим предметом. Проверьте, лучше ли полученная комбинация, чем предыдущая, и сохраните только лучшую.

Это можно оптимизировать, используя список элементов, отсортированных по цене, что позволяет прекратить итерации, когда все остальные элементы стоят дороже, чемнаш текущий бюджет. Со списком, остальные элементы могут быть выражены через индекс без необходимости создавать новые коллекции. Нам не нужно рассматривать элементы до текущей, так как это приведет к комбинациям, которые мы уже проверяли ранее:

public static Set<String> select(Map<String,Integer> available, int budget) {
    List<Map.Entry<String,Integer>> temp = new ArrayList<>(available.entrySet());
    temp.sort(Map.Entry.comparingByValue());
    Choice c = selectImpl(temp, 0, budget);
    return c == null? Collections.emptySet(): c.items;
}
private static Choice selectImpl(
    List<Map.Entry<String, Integer>> availTemp, int start, int budget) {
    Choice c = null;
    for(int ix = start; ix < availTemp.size(); ix++) {
        Map.Entry<String, Integer> e = availTemp.get(ix);
        if(e.getValue() > budget) return c;
        Choice sub;
        int cost = e.getValue(), remaining = budget - cost;
        if(remaining == 0) return new Choice(e.getKey(), budget);
        sub = selectImpl(availTemp, ix + 1, remaining);
        if(c == null || c.cost < (sub == null? cost: sub.cost + cost))
            c = sub == null? new Choice(e.getKey(),e.getValue()): sub.add(e.getKey(),cost);
    }
    return c;
}
private static final class Choice {
    final Set<String> items;
    int cost;

    Choice(String key, int c) {
        items = new HashSet<>();
        items.add(key);
        cost = c;
    }
    Choice add(String key, int c) {
        items.add(key);
        cost += c;
        return this;
    }
}

Это можно использовать как

Map<String,Integer> available = Map.of(
    "Item A", 450, "item B", 300, "Item C", 350, "item D", 200);
int budget = 900;
Set<String> picked = select(available, budget);
System.out.println("With "+budget+ ", buy "+picked
    +", consuming "+picked.stream().mapToInt(available::get).sum());
0 голосов
/ 11 октября 2019

Решение состоит в том, чтобы создать словарь всех сумм, которые вы могли потратить, и того, что было последней покупкой, которая привела вас туда. Затем возьмите наибольшее количество, которое вы найдете, и вернитесь в словарь, чтобы найти список предметов, которые вы купили.

Вот решение Python, которое делает это:

def optimal_buy (money, item_price):
    best = 0
    last_buy = {0: None}

    for item, price in item_price.iteritems():
        # Make a copy before altering the dictionary.
        prev_spent = [k for k in last_buy.keys()]
        for spent in prev_spent:
            next_spent = spent + price
            if next_spent <= money and next_spent not in last_buy:
                last_buy[next_spent] = item
                if best < next_spent:
                    best = next_spent

    answer = []
    while 0 < best:
        item = last_buy[best]
        answer.append(item)
        best = best - item_price[item]

    return sorted(answer)


print(optimal_buy(900, {'A': 450, 'B': 300, 'C': 350, 'D': 200}))
...