C ++返回具有最小硬币的数组/向量来获得值动态编程

时间:2018-04-17 20:09:25

标签: c++ arrays vector dynamic-programming minimum

我的任务是创建一个函数,该函数接收硬币的数组/向量和要达到的值。该函数不是简单地返回所需的最小硬币数量,而是必须返回一个数组/向量,该数组/向量基本上具有每种面额应使用多少硬币的信息,以便使用最少量的硬币。

例如,数组coins保持[1, 2, 5, 10],所需的值为12美分。该函数应该接受所有这些并返回一个包含以下数字的数组:[0, 1, 0, 1],表示应使用0 1美分硬币,1 2美分应使用硬币,0应使用5美分硬币,并且应使用1 10美分硬币。

我正在使用c ++并且必须使用动态编程算法,我能够做到只返回所需的最小硬币数量。但是,我不确定如何生成正确的数字来填充要返回的数组或向量。

这就是我目前所拥有的:

int *minCoins(int coins[], int size, int value)
{
    int *table = new int[value + 1];

    table[0] = 0;

    for (int i = 1; i <= value; i++)
        table[i] = INT_MAX;

    for (int i = 1; i <= value; i++)
    {
        for (int j = 0; j < size; j++)
            if (coins[j] <= i)
            {
                int sub_res = table[i - coins[j]];
                if (sub_res != INT_MAX && sub_res + 1 < table[i])
                    table[i] = sub_res + 1;
            }
    }

    //this is where I am unsure of what to do. should I return table or modify coins somehow?
}

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

我们可以另外存储用于获取apply的最后一个硬币类型table[i]而不是仅存储背包中i的最小硬币数last[i] table[i] 1}}。之后,我们可以在循环中i -= coins[last[i]]获取所有硬币,直到i变为零。

在代码中:

int *minCoins(int coins[], int size, int value)
{
    int *last = new int[value + 1];  // this line added
    int *table = new int[value + 1];
    table[0] = 0;
    for (int i = 1; i <= value; i++)
        table[i] = INT_MAX;

    for (int i = 1; i <= value; i++)
    {
        for (int j = 0; j < size; j++)
            if (coins[j] <= i)
            {
                int sub_res = table[i - coins[j]];
                if (sub_res != INT_MAX && sub_res + 1 < table[i])
                {
                    table[i] = sub_res + 1;
                    last[i] = j;  // this line added
                }
            }
    }

    int *res = new int[size];  // this will be the answer
    for (int i = 0; i < size; i++)
        res[i] = 0;

    int cur = value;  // the value left
    while (cur > 0)
    {
        res[last[cur]] += 1;  // add the current coin
        cur -= coins[last[cur]];  // proceed to the next coin
    }
    delete[] table;
    delete[] last;
    return res;
}

答案 1 :(得分:0)

你可以使用pair&lt; int,bool&gt; dp [i] [j]其中i是1到i的答案,其值为j,那么如果我们使用第i个硬币然后dp [i] [j] .second = true则为false然后在到达时结束您可以使用递归函数的最小答案,并且对于您到达的每个dp [i] [j],如果bool为真,则必须转到dp [i - 1] [j - a [i]]并添加i来回答(a是硬币的价值)否则你必须在没有做任何事情的情况下去dp [i - 1] [j]

dp update:

if(dp[i - 1][j].first < dp[i - 1][j - a[i]].first + 1)
{
    dp[i][j].second = false;
    dp[i][j].first = dp[i - 1][j].first;
}
else
{
    dp[i][j].second = true;
    dp[i][j].first = dp[i - 1][j - a[i]].first + 1;
}

递归函数:

void func(int i,int j)
{
    if(i == -1)
       return;
    if(dp[i][j].second)
       ans.push_back(i), func(i - 1,j - a[i]);
    else
       func(i - 1,j);
}