10

どのコインが使用されたかを追跡する一般的なコイン変更問題の DP ソリューションをプログラムしようとしています。これまでのところ、必要な最小量のコインを提供するために機能していますが、どのコインが何回使用されたかを取得する方法がわかりません。コインが使用されている場合、値を含む別のテーブル (ブール値) を設定しようとしましたが、正しく機能していないようです。何か案は?

public static int minChange(int[] denom, int changeAmount) 
{   
    int m = denom.length;
    int n = changeAmount + 1;

    int[][] table = new int[m][n];
    boolean[][] used = new boolean[m][n];
    for (int j = 0; j < n; j++)
        table[m - 1][j] = j;
    for (int i = 0; i < m; i++)
        table[i][0] = 0;

    for (int i = m-2; i >= 0; i--) //i denotes denominationIndex
    {
        for (int j = 1; j < n; j++) //j denotes current Amount
        {
            if (denom[i] > j)
            {
                table[i][j] = table[i+1][j];
                //used[i][j] = false;
            }
            else
            {
                table[i][j] = Math.min(1 + table[i][j-denom[i]], table[i+1][j]);
                /*Trying table for used coins
                if (1 + table[i][j-denom[i]] < table[i+1][j]) 
                    used[i][j] = true;
                else
                    used[i][j] = false;
                */
            }
        }
    }
}
4

9 に答える 9

6

このソリューションを試してください。O (M)メモリのみを使用し、 O(N*M)の複雑さがあります。

   public static int[] minChange(int[] denom, int changeAmount)
    {
        int n = denom.length;
        int[] count = new int[changeAmount + 1];
        int[] from = new int[changeAmount + 1];

        count[0] = 1;
        for (int i = 0 ; i < changeAmount; i++)
            if (count[i] > 0)
                for (int j = 0; j < n; j++)
                {
                    int p = i + denom[j];
                    if (p <= changeAmount)
                    {
                        if (count[p] == 0 || count[p] > count[i] + 1)
                        {
                            count[p] = count[i] + 1;
                            from[p] = j;
                        }
                    }
                }

        // No solutions:
        if (count[changeAmount] == 0)
            return null;

        // Build answer.
        int[] result = new int[count[changeAmount] - 1];
        int k = changeAmount;
        while (k > 0)
        {
            result[count[k] - 2] = denom[from[k]];
            k = k - denom[from[k]];
        }

        return result;
    }
于 2013-11-25T08:02:50.657 に答える
3
public static int minimumNumberOfWays(int []deno, int amount){
    int dp[] = new int[amount+1];
    dp[0]=0;
    int []prevCoin = new int[amount+1];  
    for(int j=1;j<=amount;j++){
        dp[j]=Integer.MAX_VALUE;
        for(int i=0;i<deno.length;i++){
            if(deno[i]<=j && (1+dp[j-deno[i]] < dp[j]) ){               
                dp[j]=1+dp[j-deno[i]];
                prevCoin[j]=deno[i];
            }                   
        }
    }

    int result = dp[amount];
    List<Integer> coinsAdded = new ArrayList<Integer>();
    for(int i=amount;i>=1;){
        coinsAdded.add(prevCoin[i]);
        int j=i;
        i=amount-prevCoin[i];
        amount = amount - prevCoin[j];
    }
    Integer [] coins = coinsAdded.toArray(new Integer[coinsAdded.size()]);
    System.out.println( Arrays.toString(coins)); 
于 2015-04-21T13:29:31.440 に答える
0
public class CoinChange {

    public static void main(String[] args) {
        int[] coins = {1,2,10,5};       
        int amt = 37;       
        makeChange(coins, amt); 
    }

    public static void makeChange(int[] coins, int amount){
        //Sorting the coins
        Arrays.sort(coins);

        int n = coins.length - 1;


        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

        while(amount > 0)
        {
            if(coins[n] <= amount)
            {
                int val = 1;
                if(map.containsKey(coins[n]))
                {
                    val = map.get(coins[n]);
                    val = val+1;
                }

                map.put(coins[n], val);

                amount = amount - coins[n];

            }
            else
            {
                n--;
            }

        }

        for(Map.Entry<Integer, Integer> entry: map.entrySet()){

            System.out.println(entry.getKey() +":" + entry.getValue());
        }
    }
}
于 2015-05-14T13:58:12.370 に答える
0
public class CoinChange {
/**
 * Get mini num of coins
 * 
 * @param coinValues
 *            coins
 * @param totalMoney
 *            total money
 * @return
 */
public int coinNum(int[] coinValues, int totalMoney) {
    List<Integer> coins = new ArrayList<Integer>();
    coins.add(0);
    for (int i = 1; i <= totalMoney; i++) {
        int coin = nearestCoin(i, coinValues);
        int coinNum = coins.get(i - coin) + 1;
        coins.add(coinNum);
    }
    return coins.get(totalMoney);
}

/**
 * Get the coin nearest to specified value.
 */
private int nearestCoin(int value, int[] coinValues) {
    int res = 0;
    int nearest = Integer.MAX_VALUE;
    for (int coinValue : coinValues) {
        if (coinValue <= value) {
            int distance = value - coinValue;
            if (distance < nearest) {
                nearest = distance;
                res = coinValue;
            }
        }
    }
    return res;
}

@Test
public void test() throws Exception {
    int res = coinNum(new int[] { 1, 2, 3, 5, 11 }, 81);
    System.out.println(res);
}

}

于 2015-12-30T10:37:33.090 に答える
0

ソリューションを再構築するには、次の疑似コードを使用します: -

solutionSet = []

i = denom.length-1

j = changeAmount

While(i>=0) {

   if(1+table[i][j-denom[i]]<table[i+1][j]) {
         solutionSet.add(denom[i])
         j = j - denom[i]
     }
   i--
}

注:ソリューションを格納するために必要な以外に、ここで余分なメモリを使用する必要はありません。

于 2013-11-25T12:01:40.407 に答える
-1

動的計画法を使用したソリューション ::

public int coinchange2(ArrayList<Integer> A, int B) {
    int[] dp = new int[B+1];

    dp[0]=1;

    for(int i=0;i<A.size();i++){
        for(int j=A.get(i);j<=B;j++)
        {
            dp[j]=(dp[j]+dp[j-A.get(i)])%1000007;
        }
    }
    return dp[B];
}
于 2019-02-09T11:32:33.170 に答える