Clasa a XI-a · Metoda backtrackingRead in English

Plata unei sume cu monede date în C++

În engleză: Paying a sum with given coins

ExponențialăC++1777 de linii1 exemplu

Ideea

Avem n tipuri de monede, cu valorile v[1..n], din fiecare câte vrem. Afișăm toate modurile de a plăti exact suma S. x[k] este numărul de monede de tipul k și ia valori de la 0 până la cât mai încape în suma rămasă. Ultimul tip de monedă nu mai are de ales: trebuie să acopere exact restul. Fiecare soluție se afișează ca sumă de termeni numar*valoare.

Descrierea în engleză

There are n coin types with values v[1..n], as many of each as we want. We print all ways of paying exactly the sum S. x[k] is the number of coins of type k and takes values from 0 up to as many as still fit in the remaining sum. The last coin type has no choice: it must cover the remainder exactly. Every solution is printed as a sum of terms count*value.

Complexitate
exponențială în n (numărul de combinații încercate)
Clasa
Clasa a XI-a (Grade 11)

Exemple

Exemplul 1

Intrare

3 5
1 2 5

Ieșire așteptată

1*5
1*1 + 2*2
3*1 + 1*2
5*1
Moduri: 4

Codul C++

Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.

plata-unei-sume-cu-monede.cpp
/*
 * Titlu: Plata unei sume cu monede date
 * Clasa: 11
 * Capitol: Metoda backtracking
 * Descriere: Avem n tipuri de monede, cu valorile v[1..n], din fiecare câte vrem.
 *            Afișăm toate modurile de a plăti exact suma S. x[k] este numărul de monede
 *            de tipul k și ia valori de la 0 până la cât mai încape în suma rămasă.
 *            Ultimul tip de monedă nu mai are de ales: trebuie să acopere exact restul.
 *            Fiecare soluție se afișează ca sumă de termeni numar*valoare.
 * Complexitate: exponențială în n (numărul de combinații încercate)
 *
 * Exemplu
 * Intrare:
 * 3 5
 * 1 2 5
 * Ieșire:
 * 1*5
 * 1*1 + 2*2
 * 3*1 + 1*2
 * 5*1
 * Moduri: 4
 */
#include <iostream>
using namespace std;

int n, S, v[20], x[20], moduri = 0;

void afiseaza()
{
    bool primul = true;
    for (int i = 1; i <= n; i++)
    {
        if (x[i] > 0)
        {
            if (!primul)
            {
                cout << " + ";
            }
            cout << x[i] << '*' << v[i];
            primul = false;
        }
    }
    cout << '\n';
}

void back(int k, int ramas)
{
    if (k == n)
    {
        // ultimul tip trebuie să acopere exact restul
        if (ramas % v[n] == 0)
        {
            x[n] = ramas / v[n];
            moduri++;
            afiseaza();
        }
        return;
    }
    for (int c = 0; c * v[k] <= ramas; c++)
    {
        x[k] = c;
        back(k + 1, ramas - c * v[k]);
    }
}

int main()
{
    cin >> n >> S;
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i];
    }
    back(1, S);
    cout << "Moduri: " << moduri << '\n';
    return 0;
}

Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.