Titulo:
Dado nn números positivos, ZJM puede seleccionar exactamente KK de ellos que suman SS. ¡Ahora ZJM se pregunta cuántas formas de obtenerlo!
Entrada:
La primera línea, un número entero T <= 100T <= 100, indica el número de casos de prueba. Para cada caso, hay dos líneas. La primera línea, tres enteros indican nn, KK y SS. La segunda línea, nn enteros, indican los números positivos.
Salida:
Para cada caso, un número entero indica la respuesta en una línea independiente.
Entrada de muestra:
1
10 3 10
1 2 3 4 5 6 7 8 9 10
Salida de muestra:
4 4
Ideas:
Esta pregunta requiere que seleccionemos K de n números y hagamos la suma S. Si usamos el método de enumeración, hay un total de 2 n veces. La complejidad en este momento es obviamente demasiado alta, por lo que necesitamos En el proceso de selección de números, se eliminan las condiciones de error innecesarias, tales como: se han seleccionado los números K pero aún menos que S; se han seleccionado los números K pero su suma es mayor que S. De acuerdo con la idea de búsqueda en profundidad de dfs, el método recursivo se utiliza para seleccionar y deseleccionar secuencialmente el número n de entradas. Para situaciones irrazonables en el proceso de recursión, regrese directamente al nivel anterior y detenga la rama recursiva Cuando se alcanza el objetivo, regresa desde el último número y agrega uno al tot cuando regresa.
Código:
#include <iostream>
#include <list>
using namespace std;
int K, tot = 0, n, S;
void solve0(int i, int sum, int *a, list<int> &res)
{
if (res.size() == K && sum == 0)
{
tot++;
return;
}
if (i >= n)
return;
if (res.size() > K || sum < 0)
return;
solve0(i + 1, sum, a, res);
res.push_back(a[i]);
solve0(i + 1, sum - a[i], a, res);
res.pop_back();
}
int main()
{
int cases;
list<int> res;
cin >> cases;
for (int i = 0; i < cases; i++)
{
res.clear();
cin >> n >> K >> S;
int *temp = new int[n];
for (int j = 0; j < n; j++)
cin>>temp[j];
tot = 0;
solve0(0,S,temp,res);
cout << tot << endl;
}
return 0;
}