换钱的最少货币数

题目:给定数组arr, arr中所有的值都为正数且不重复。每个值代表一中面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。
进阶:每种面值的货币只可以使用一张

#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int minCoins1(vector<int>& arr, int aim)
{
    if(arr.size() == 0 || aim < 0)
        return -1;
    int n = arr.size();
    int max = INT_MAX;
    //在可以使用任意的arr[0..i]的情况下,组成j的最小张数
    vector<vector<int> > dp(n, vector<int>(aim + 1));
    for(int j = 1; j <= aim; ++j)
    {
        dp[0][j] = max;
        if(j - arr[0] >= 0 && dp[0][j - arr[0]] != max)
        {
            dp[0][j] = dp[0][j - arr[0]] + 1;
        }
    }
    int left = 0;
    for(int i = 1; i < n; ++i)
    {
        for(int j = 1; j <= aim; ++j)
        {
            left = max;
            if(j - arr[i] >= 0 && dp[i][j - arr[i]] != max)
                left = dp[i][j - arr[i]] + 1;
            dp[i][j] = min(dp[i - 1][j], left);
        }
    }
    return dp[n - 1][aim] != max ? dp[n - 1][aim] : -1;
}

int minCoins2(vector<int>& arr, int aim)
{
    if(arr.size() == 0 || aim < 0)
        return -1;
    int n = arr.size();
    int max = INT_MAX;
    vector<int> dp(aim + 1);
    for(int i = 1; i <= aim; ++i)
    {
        dp[i] = max;
        if(i - arr[0] >= 0 && dp[i - arr[0]] != max)
            dp[i] = dp[i - arr[0]] + 1;
    }
    int left = 0;
    for(int i = 1; i < n; ++i)
    {
        for(int j = 1; j < aim + 1; ++j)
        {
            left = max;
            if(j - arr[i] >= 0 && dp[j - arr[i]] != max)
                left = dp[j - arr[i]] + 1;
            dp[j] = min(dp[j], left);
        }
    }
    return dp[aim] != max ? dp[aim] : -1;
}
//进阶
int minCoins3(vector<int>& arr, int aim)
{
    if(arr.size() == 0 || aim < 0)
        return -1;
    int n = arr.size();
    int max = INT_MAX;
    vector<vector<int> > dp(n, vector<int>(aim + 1));
    for(int j = 1; j <= aim; ++j)
    {
        dp[0][j] = max;
    }
    if(arr[0] <= aim)
    {
        dp[0][arr[0]] = 1;
    }

    int left = 0;
    for(int i = 1; i < n; ++i)
    {
        for(int j = 1; j <= aim; ++j)
        {
            left = max;
            if(j - arr[i] >= 0 && dp[i - 1][j - arr[i]] != max)
                left = dp[i - 1][j - arr[i]] + 1;
            dp[i][j] = min(dp[i - 1][j], left);
        }
    }
    return dp[n - 1][aim] != max ? dp[n - 1][aim] : -1;
}
int minCoins4(vector<int>& arr, int aim)
{
     if(arr.size() == 0 || aim < 0)
        return -1;
    int n = arr.size();
    int max = INT_MAX;
    vector<int> dp(aim + 1);
     for(int j = 1; j <= aim; ++j)
    {
        dp[j] = max;
    }
    if(arr[0] <= aim)
    {
        dp[arr[0]] = 1;
    }
  int left = 0;
    for(int i = 1; i < n; ++i)
    {
        for(int j = aim; j >= 1; --j)//从后向前更新,保证数组中需要的元素是未被更新的,既是上一行的
        {
            left = max;
            if(j - arr[i] >= 0 && dp[j - arr[i]] != max)
                left = dp[j - arr[i]] + 1;
            dp[j] = min(dp[j], left);
        }
    }
    return dp[aim] != max ? dp[aim] : -1;

}
int main()
{
    vector<int> ivec;
    ivec.push_back(5);
    ivec.push_back(2);
    ivec.push_back(3);
    cout << minCoins1(ivec, 20) << endl;
     cout << minCoins1(ivec, 1) << endl;
     cout << "===============================" << endl;
      cout << minCoins2(ivec, 20) << endl;
     cout << minCoins2(ivec, 1) << endl;
     cout << "===============================" << endl;
     cout << minCoins3(ivec, 20) << endl;
     cout << minCoins3(ivec, 7) << endl;
     cout << "===============================" << endl;
     cout << minCoins4(ivec, 20) << endl;
     cout << minCoins4(ivec, 7) << endl;
     cout << "===============================" << endl;
}

猜你喜欢

转载自blog.csdn.net/wzc2608/article/details/80909746