Java 用蛮力组合硬币
我有一些代码可以用暴力解决以下问题: 给定一组x硬币和要达到的目标金额,达到该目标所需的最少硬币数量是多少 迄今为止的守则:Java 用蛮力组合硬币,java,optimization,dynamic-programming,Java,Optimization,Dynamic Programming,我有一些代码可以用暴力解决以下问题: 给定一组x硬币和要达到的目标金额,达到该目标所需的最少硬币数量是多少 迄今为止的守则: import java.util.ArrayList; import java.util.Arrays; public class coinsSum { public static int min = Integer.MAX_VALUE; public static int[] combination; public static final i
import java.util.ArrayList;
import java.util.Arrays;
public class coinsSum {
public static int min = Integer.MAX_VALUE;
public static int[] combination;
public static final int TARGET = 59;
public static void main(String[] args) {
long start = System.nanoTime();
int[] validCoins = new int[] {1, 2, 5, 10, 20};
Arrays.sort(validCoins);
int len = validCoins.length;
ArrayList<Integer> maxList = new ArrayList<Integer>();
for(int c : validCoins) {
maxList.add(TARGET / c);
}
int[] max = new int[len];
for(int i = 0; i < len; i++) {
max[i] = maxList.get(i).intValue();
}
permutations(new int[len], max, validCoins, 0); // bread&butter
if(min != Integer.MAX_VALUE) {
System.out.println();
System.out.println("The combination " + Arrays.toString(combination) + " uses " + min + " coins to make the target of: " + TARGET);
} else {
System.out.println("The target was not reachable using these coins");
}
System.out.println("TOOK: " + (System.nanoTime() - start) / 1000000 + "ms");
}
public static void permutations(int[] workspace, int[] choices, int[] coins, int pos) {
if(pos == workspace.length) {
int sum = 0, coinCount = 0;
System.out.println("TRYING " + Arrays.toString(workspace));
for(int a = 0; a < coins.length; a++) {
sum += workspace[a] * coins[a];
coinCount += workspace[a];
}
if(sum == TARGET) {
// System.out.println(Arrays.toString(n)); //valid combinations
if(coinCount < min) {
min = coinCount;
combination = workspace;
System.out.println(Arrays.toString(combination)+" uses " + min + " coins");
}
}
return;
}
for(int i = 0; i <= choices[pos]; i++) {
workspace[pos] = i;
permutations(workspace, choices, coins, pos + 1);
}
}
}
import java.util.ArrayList;
导入java.util.array;
公共类货币{
公共静态int min=Integer.MAX_值;
公共静态int[]组合;
公共静态最终整数目标=59;
公共静态void main(字符串[]args){
长启动=System.nanoTime();
int[]validCoins=newint[]{1,2,5,10,20};
Arrays.sort(validCoins);
int len=validCoins.length;
ArrayList maxList=新的ArrayList();
用于(int c:validCoins){
maxList.add(目标/c);
}
int[]max=新的int[len];
对于(int i=0;i 对于(int i=0;i您可以对硬币数组进行排序。然后从右向左,不断从目标值中减去,直到硬币比目标的剩余值大。在硬币数组中向左移动并重复此过程
例如:
{1, 2, 5, 10, 20}
num = 59
Try coins from right to left:
59 - 20 = 39
So far coins used [20]
39 - 20 = 19
So far coins used [20,20]
19 - 20 = -1, Can't use 20!
19 - 10 = 9
So far coins used [20,20,10]
9 - 10 = -1, Can't use 10!
9 - 5 = 4
So far coins used [20,20,10,5]
4 - 5 = -1, Can't use 5!
4 - 2 = 2
So far coins used [20,20,10,5,2]
2 - 2 = 0
So far coins used [20,20,10,5,2,2]
Total coin used 6
这里是python中的一个解决方案,它使用动态编程来找到达到目标值的最小硬币数
该算法的工作原理如下
dp[i][target] = minimum number of coins required required to acheive target using first i coin
dp[i][target] = min(dp[i-1][target],dp[i-1][target-coin[i]]+1)
dp[i-1][target] denotes not using the ith coin
dp[i-1][target-coin[i]] denotes making use of ith coin
因为对于每一枚硬币,你都在检查是否包含它,所以算法会枚举所有可能的组合
这是上述算法的空间优化版本
maxvalue = 10 ** 9
def minchange(coins, target):
no_of_coins = len(coins)
dp = [maxvalue for i in range(target + 1) ]
dp[0] = 0
for i in range(no_of_coins):
for j in range(coins[i], target + 1):
dp[j] = min(dp[j], dp[j - coins[i]] + 1)
return dp[target]
我发现了一种动态规划方法,这种方法肯定没有得到优化,但如果有人感兴趣的话,对于目标数字高达10000也不算太坏
import java.util.*;
public class coinSumMinimalistic {
public static final int TARGET = 12003;
public static int[] validCoins = {1, 3, 5, 6, 7, 10, 12};
public static void main(String[] args) {
Arrays.sort(validCoins);
sack();
}
public static void sack() {
Map<Integer, Integer> coins = new TreeMap<Integer, Integer>();
coins.put(0, 0);
int a = 0;
for(int i = 1; i <= TARGET; i++) {
if(a < validCoins.length && i == validCoins[a]) {
coins.put(i, 1);
a++;
} else coins.put(i, -1);
}
for(int x = 2; x <= TARGET; x++) {
if(x % 5000 == 0) System.out.println("AT: " + x);
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i = 0; i <= x / 2; i++) {
int j = x - i;
list.add(i);
list.add(j);
}
coins.put(x, min(list, coins));
}
System.out.println("It takes " + coins.get(TARGET) + " coins to reach the target of " + TARGET);
}
public static int min(ArrayList<Integer> combos, Map<Integer, Integer> coins) {
int min = Integer.MAX_VALUE;
int total = 0;
for(int i = 0; i < combos.size() - 1; i += 2) {
int x = coins.get(combos.get(i));
int y = coins.get(combos.get(i + 1));
if(x < 0 || y < 0) continue;
else {
total = x + y;
if(total > 0 && total < min) {
min = total;
}
}
}
int t = (min == Integer.MAX_VALUE || min < 0) ? -1:min;
return t;
}
public static void print(Map<Integer, Integer> map) {
for(Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("[" + entry.getKey() + ", " + entry.getValue() + "]");
}
System.out.println();
}
}
import java.util.*;
公共类货币{
公共静态最终整数目标=12003;
公共静态int[]validCoins={1,3,5,6,7,10,12};
公共静态void main(字符串[]args){
Arrays.sort(validCoins);
麻袋();
}
公共静态void sack(){
地图硬币=新的树形地图();
硬币。投入(0,0);
int a=0;
对于(inti=1;i),如果代码有效,而您只是在寻求改进,那么请转到“任何方式?”是的。其他问题太广泛了,提到的代码审查网站是个好主意。我确实发布了一个版本,但没有收到回复,所以我在这里寻求帮助@markspace我将编辑这个问题,然后不要让它变得不那么一般。你可以重复吗coins@Amir是的,你可以拥有无限数量的任何硬币,但如果你有超过T/C的硬币一枚硬币它会超出目标,其中T是目标,c是硬币价值,例如,T=5,c=2,5/2=2在有效的解决方案中是最有可能的。这适用于某些硬币列表(美国硬币就是一个例子),但不适用于其他硬币。例如,如果你有{1,3,4}如果你想得到6,那么这个算法会得到一个[4,1,1]的答案,但最优值是[3,3]