当然,解决这个问题,用递归是费力不讨好,但有递归确实很有意思。
看了各位仁兄的贴子,收获颇多。(稍侯,我再琢磨各位的思路)
我先说说我对这个问题的看法,请各位指正。
将各种情况罗列出来以后,发现它确实是可以用数学的递归算法来解决。
我们设函数f(n,r),可以得到一个从1..n的数列中选r个数,而得到的一组数。
这里,我们用向量的形式表示某一组数,然后得到的就是向量的集合。
就是说f(n,r)得到一组r维向量的集合。
如f(5,3)={(5,4,3);(5,4,2);(5,4,1);(5,4,3);(5,3,2);(5,3,1);(5,2,1);(4,3,2);(4,3,1);(3,2,1);}
那么有:
递归公式:f(n,r)=n ※ f(n-1,r-1) + f(n-1,r)
其中※运算为左侧元素填加至右侧r-1向量中,而形成r向量 的运算符
递归终止条件:f(n,0)={} f(n,1)={(1)(2)..
} f(n,n)={(1,2..n)}
正好最近看C++看的头痛,那就用C++写了,因为C++中正好有vector(向量)对象,
不知道Object Pascal该怎么写?
/*
* 从1..n序列中选r个数,用递归实现
* 递归公式 f(n,r)=n ※ f(n-1,r-1) + f(n-1,r)
* 其中 ※ 为左侧元素填加至右侧r-1维向量中,而形成r维向量
* 终止条件 f(n,0)={} f(n,1)={(1),(2)..
} f(n,n)={(1,2,..n)}
*
*/
#include <iostream.h>
#include <conio.h>
#include <vector>
#include <system.hpp>
#include <dstring.h>
// ※ 运算符
vector <AnsiString> ad(int n, const vector<AnsiString> &
vecN)
{
vector <AnsiString> vecAd;
AnsiString strN;
vecAd=vecN;
for (int i=0 ;i<vecAd.size();++i)
{
strN=vecAd
;
strN=strN+IntToStr((unsigned));
vecAd=strN;
}
return vecAd;
}
//两个向量的+ 运算
vector <AnsiString> plusN(const vector<AnsiString> &
lha,const vector<AnsiString> &
rha)
{
vector <AnsiString> vecPN;
AnsiString elem;
vecPN=lha;
for (int i=0;
i<rha.size();++i)
{
elem=rha;
vecPN.push_back(elem);
}
return vecPN;
}
//求f(n,r)
vector <AnsiString> select_num(int n,int r)
{
vector <AnsiString> vecSNum;
AnsiString elem="";
if (r==0 || n==0)
{
vecSNum.clear();
return vecSNum;
}
if (r==1)
{
vecSNum.clear();
for (int i=1;i<=n;++i)
{
elem=IntToStr((unsigned int)(i));
vecSNum.push_back(elem);
}
return vecSNum;
}
if (n==r)
{
vecSNum.clear();
elem="";
for (int i=1;i<=n;i++)
{
elem=elem+IntToStr((unsigned)(i));
}
vecSNum.push_back(elem);
return vecSNum;
}
//递归
vecSNum=plusN(ad(n,select_num(n-1,r-1)),select_num(n-1,r));
return vecSNum;
}
int main()
{
vector <AnsiString> SN;
SN=select_num(30,1);
for (int i=0;
i<SN.size();++i)
{
cout<<SN<<endl;
}
getch();
return 0;
}
//---------------------------------------------------------------------------