O problema da metade do conjunto de design e análise de algoritmos
Descrição do Problema
É necessário encontrar o número de números com as seguintes propriedades (incluindo o número natural de entrada n):
primeiro insira um número natural n (n <= 500) e, em seguida, processe este número natural da seguinte maneira:
- Fazer nada
- Adicione um número natural à sua esquerda, mas o número natural não pode exceder a metade do número original
- Depois de adicionar o número, continue a processar de acordo com esta regra até que nenhum número natural possa ser adicionado
Se você inserir 6, haverá
6
16
26
126
36
136
saída 6
analise de problemas
Podemos facilmente encontrar a fórmula de recorrência para o número de conjuntos de meio-número:
f (n) = 1 + ∑ i = 1 n / 2 f (i) f (n) = 1 + \ sum_ {i = 1} ^ {n / 2 } f (i)f ( n )=1+i = 1∑n / 2f ( i )
Usamos recursão para realizar cálculos recursivos.Para evitar cálculos repetidos, usamos busca de memória.
Implementação de algoritmo
#include <iostream>
#include <cstring>
#define N 500
using namespace std;
int a[N] = {
0}; //存储计算过的数据 初始化所有值为零
//求半数集算法
int halfSet(int);
int main()
{
int n;
cout<<"请输入n:";
cin>>n;
cout<<n<<"的半数集元素数量为:"<<halfSet(n)<<endl;
return 0;
}
int halfSet(int n){
if(a[n] > 0) return a[n];
int ret = 1;
for(int i=1;i<=n/2;i++){
ret = ret + halfSet(i);
}
a[n] = ret;
return ret;
}
No entanto, há falhas no algoritmo acima e haverá subproblemas repetitivos. Por exemplo, há dois 1224s na metade de 24. Os métodos de geração são diferentes, mas os resultados são os mesmos. Precisamos melhorar o algoritmo novamente.
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <set>
using namespace std;
//求半数集算法 改进 无重复子问题
void halfSet(int,set<string>&,string);
int main()
{
int n;
set<string> s;
char *str = new char[3];
cout<<"请输入n:";
cin>>n;
if(n > 500){
cout<<"数据超范围!";
exit(0);
}
halfSet(n,s,string(itoa(n,str,10)));
cout<<n<<"的半数集元素数量为:"<<s.size()+1<<endl;
return 0;
}
void halfSet(int n,set<string> &s,string str){
char *strs = new char[3];
string mStr;
for(int i=1;i<=n/2;i++){
mStr = string(itoa(i,strs,10)) + str;
s.insert(mStr);
halfSet(i,s,mStr);
}
}
Recomendado por outros artigos neste blog
Registro sobre a inicialização automática da matriz de inteiros C ++ para zero
Seleção de tempo linear para projeto e análise de algoritmo
Divida e conquiste exercícios de estratégia para design e análise de algoritmo (parte 2)
Divida e conquiste exercícios de estratégia para design e análise de algoritmos (on)
Divida e conquiste estratégia para design e análise de algoritmos
Projeto de algoritmo e análise de exercícios de algoritmo recursivo (parte 2)
Projeto de algoritmo e análise de exercícios de algoritmo recursivo (on)