#java #dynamic
Вопрос:
Я столкнулся с проблемой реализации, пытаясь решить эту классическую проблему с помощью DP. Задача состоит в том, чтобы получить набор монет и вернуть их наилучшим способом, дав наименьшее количество монет.
import java.util.*;
class coin4
{
static int coin_values[] = {16, 4, 8};
static Map<Integer, Vector<Integer>> memo;
static Vector<Integer> give(int n)
{
if(memo.containsKey(n))
return memo.get(n);
if(n<0)
return null;
if(n==0)
return new Vector<Integer>();
Vector<Integer> bestResult = null;
for(Integer coin : coin_values)
{
Vector<Integer> result = give(n-coin);
if(result != null)
{
result.add(coin);
if(bestResult == null || bestResult.size() > result.size())
bestResult = resu<
}
}
memo.put(n, bestResult);
return bestResu<
}
public static void main(String[] args)
{
int n=24;
memo = new HashMap<>();
Vector<Integer> result = give(n);
if(result==null)
System.out.println("No solution available");
else
for(Integer value: result)
System.out.println(value);
}
}
Он возвращает вектор, содержащий [16, 4, 4, 8], ожидая [16, 8].
Любая помощь будет очень признательна!
ИЗМЕНИТЬ 25/07: теперь это работает идеально! wallet.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class InfiniteWallet {
private Map<Integer, ArrayList<Integer>> memo;
private ArrayList<Integer> coinValues = new ArrayList<Integer>();
public void addCoin(int coin) {
coinValues.add(coin);
}
public ArrayList<Integer> giveChange(int change) {
memo = new HashMap<Integer, ArrayList<Integer>>();
Collections.sort(coinValues);
Collections.reverse(coinValues);
return give(change);
}
private ArrayList<Integer> give(int n) {
if (memo.containsKey(n))
if (memo.get(n) != null)
return new ArrayList<Integer>(memo.get(n));
else
return null;
if (n < 0)
return null;
if (n == 0)
return new ArrayList<Integer>();
ArrayList<Integer> bestResult = null;
for (Integer coin : coinValues) {
ArrayList<Integer> result = give(n - coin);
if (result != null) {
result.add(coin);
if (bestResult == null || bestResult.size() > result.size())
bestResult = resu<
}
}
memo.put(n, bestResult);
if (bestResult != null)
return new ArrayList<Integer>(bestResult);
return null;
}
ArrayList<Integer> getCoinValues(){
return new ArrayList<Integer>(coinValues);
}
}
main.java
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
InfiniteWallet wallet = new InfiniteWallet();
wallet.addCoin(5);
wallet.addCoin(395);
wallet.addCoin(146);
List<Integer> result = wallet.giveChange(768);
if (result == null)
System.out.println("No solution available");
else
for (Integer coin : wallet.getCoinValues())
System.out.println(coin " " Collections.frequency(result, coin));
System.out.println();
}
}
Комментарии:
1. В коде слишком много проблем. Если вы пытаетесь выполнять рекурсивные вызовы, я бы предложил вам сначала потренироваться с факториальными упражнениями и изучить статические и переменные экземпляра. Если вы настаиваете на этом коде, добавьте»System.out.println «(«n:» n); просто внутри
give(n)
метода, чтобы лучше следить за выполнением вашего кода.2. Спасибо за предложения 🙂 я пытался переписать на Java код, написанный в этом видео: youtu.be/oBt53YbR9Kk
Ответ №1:
При извлечении результатов memo
вам необходимо вернуть копию , если вы хотите внести изменения в кэшированный вектор. Например, когда вы делаете:
result.add(coin)
если вектор result
был получен из memo
, то вы добавите coin
его к исходному вектору (и, следовательно memo
, также измените).
Вы можете исправить это, просто (я бы сказал, одним из способов исправить это) вернув копию вектора, memo
а не оригинал. Просто замените:
if(memo.containsKey(n))
return memo.get(n);
с
if(memo.containsKey(n))
return new Vector(memo.get(n));
Это не самый эффективный способ исправить это, но это простое решение.
Комментарии:
1. Спасибо вам за вашу помощь! Обычно я работаю на c , поэтому по умолчанию большинство вещей передается как копия! Я хотел переписать код в этом видео youtu.be/oBt53YbR9Kk