Título:
Dados nn números positivos, o ZJM pode selecionar exatamente KK deles que somam SS. Agora ZJM se pergunta quantas maneiras de obtê-lo!
Entrada:
A primeira linha, um número inteiro T <= 100T <= 100, indica o número de casos de teste. Para cada caso, há duas linhas. A primeira linha, três números inteiros, indica nn, KK e SS. A segunda linha, nn inteiros, indica os números positivos.
Resultado:
Para cada caso, um número inteiro indica a resposta em uma linha independente.
Entrada de amostra:
1
10 3 10
1 2 3 4 5 6 7 8 9 10
Saída de amostra:
4
Idéias:
Essa pergunta exige que você selecione K dentre n números e faça a soma S. Se usarmos o método de enumeração, haverá um total de 2 n vezes.A complexidade neste momento é obviamente muito alta, por isso precisamos No processo de seleção de números, condições de erro desnecessárias são eliminadas, como: K números foram selecionados, mas ainda menos que S; K números foram selecionados, mas sua soma é maior que S. De acordo com a idéia da pesquisa profunda do dfs, o método recursivo é usado para selecionar e desmarcar seqüencialmente o número n de entradas.Para situações não razoáveis no processo de recursão, retorne diretamente ao nível anterior e pare o ramo recursivo. Quando o objetivo é atingido, ele retorna do último número e adiciona um ao tot ao retornar.
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;
}