I solve the problem of the exchange of coins. The condition is shown below. The problem is that all the solutions that I have experienced occupy a lot of memory. And not applicable for large input data such as for 1 000 000 000 . The question is how can you optimize solutions for large numbers? Or maybe there is some more effective idea to solve this problem?
The task:
1≤n≤30 numbers 1≤n≤30 and 1≤w≤10^9 and the set of numbers 1≤v[1],…,v[n]≤10^9 find the minimum number k for which the number w can be represented as the sum of k numbers from the set {v[1],…,v[n]} . Each number in the set can be used any number of times. It is known that there is a unit in the set and that for any pair of numbers from the set one of them is divided by the other. It is guaranteed that in the optimal answer the number of items does not exceed 10^4 .
Print the number k and the terms themselves.
Sample Input: 4 90 1 2 10 50 Sample Output: 5 50 10 10 10 10 C ++ solution:
#include <iostream> #include <vector> #include <string> #include <climits> #include <algorithm> std::vector<int> get_best_coins(std::vector<int>& coins, int target) { std::vector<int> costs; costs.push_back(0); std::vector<int> coins_used; for (int i = 1; i <= target; i++) { int bestCost = INT_MAX; int bestCoin = -1; for (std::vector<int>::iterator coin = coins.begin() ; coin != coins.end(); ++coin){ if (*coin <= i) { int cost = 1 + costs[i - *coin]; if (cost < bestCost) { bestCost = cost; bestCoin = *coin; } } } costs.push_back(bestCost); coins_used.push_back(bestCoin); } std::vector<int> ret; while (target > 0) { ret.push_back(coins_used[target -1]); target -= coins_used[target - 1]; } return ret; } int main() { int n; std::cin >> n; int w; std::cin >> w; std::vector<int> v; int input; for (int i = 0; i < n; i++) { std::cin >> input; v.push_back(input); } std::sort(v.begin(), v.end()); std::vector<int> result = get_best_coins(v, w); std::cout << result.size() << " "; for (std::vector<int>::iterator coin = result.begin() ; coin != result.end(); ++coin) { std::cout << *coin << " "; } return 0; } Python solution. Option 1:
import sys, math def dpMakeChange(coinValueList,change,minCoins,coinsUsed): for cents in range(change+1): coinCount = cents newCoin = 1 for j in [c for c in coinValueList if c <= cents]: if minCoins[cents-j] + 1 < coinCount: coinCount = minCoins[cents-j]+1 newCoin = j minCoins[cents] = coinCount coinsUsed[cents] = newCoin return minCoins[change] def printCoins(coinsUsed,change): coin = change while coin > 0: thisCoin = coinsUsed[coin] print(thisCoin), coin = coin - thisCoin def main(): input = sys.stdin.read() tokens = input.split() n = int(tokens[0]) amnt = int(tokens[1]) clist = [] for i in range(n): clist.append(int(tokens[i + 2])) coinsUsed = [0]*(amnt+1) coinCount = [0]*(amnt+1) print("{0}".format(dpMakeChange(clist,amnt,coinCount,coinsUsed))), printCoins(coinsUsed,amnt) main() Python solution. Option 2:
import sys def get_best_coins(coins, target): costs = [0] coins_used = [None] for i in range(1,target + 1): bestCost = sys.maxsize bestCoin = -1 for coin in coins: if coin <= i: cost = 1 + costs[i - coin] if cost < bestCost: bestCost = cost bestCoin = coin costs.append(bestCost) coins_used.append(bestCoin) ret = [] while target > 0: ret.append(coins_used[target]) target -= coins_used[target] return ret input = sys.stdin.read() tokens = input.split() n = int(tokens[0]) target = int(tokens[1]) coins = [] for i in range(n): coins.append(int(tokens[i + 2])) result = get_best_coins(coins, target) print (len(result)), for p in result: print(p),