S
sqsq69696
Unregistered / Unconfirmed
GUEST, unregistred user!
我是初学DELPHI,对PASCAL语言不熟,想请一位高手帮助把下面这个C++语言有关"从N数中选10的算法"用PASCAL语言完整地描述出来.有关从N个数中选10的算法,我试过递归算法,但30选10共3000多万组数据在奔四的机器上用了3分多钟,时间太长.而用上面这个C++算法,在一个落后的奔一的机器上,同样数据只用了33秒,差距太大.我想知道这个C++算法用PASCAL该如何描述?
分析:一个数组,其下标表示1到m个数,数组元素的值为1表示其下标代表的数被选中,为0则没选中。首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。例如求5中选3的组合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
程序如下:
#include "stdio.h"
#include "time.h"
unsigned char number[100]
//最多求100个数的组合。
unsigned int m,n;// 2<=m<=100,n<m
char tmpbuf[128]
time_t ltime
struct tm *today
void printtime(void) //打印当前时间的函数
{
time(<ime)
today = localtime(<ime )
strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S",today)
printf("%s/n",tmpbuf)
}
void inition() //初始化
{
unsigned int i
for(i=0;i<n;i++)
number=1
}
void output() //输出组合结果
{
unsigned int i
for(i=0;i<m;i++)
if(number)
printf("%02d ",i+1)
printf("/n"
}
void main()
{
unsigned long count
//计数组合个数
unsigned int i,j,k,l
bool findfirst,end,swap
end=false
printf("please input m:"
scanf("%d",&m)
//输入m
printf("please input n:"
scanf("%d",&n)
//输入n
printtime()
//打印开始时间
inition()
//初始化
//output()
//屏蔽掉结果输出以节约时间
count=1
j=m
while(!end)
{
findfirst=false
swap=false
//标志复位
for(i=0;i<j;i++)
{
if(!findfirst &&
number)
{
k=i
//k记录下扫描到的第一个数
findfirst=true
//设置标志
}
if(number &&
!number[i+1]) //从左到右扫描第一个“10”组合
{
number=0
number[i+1]=1
swap=true
//设置交换标志
for(l=0;l<i-k;l++)
number[l]=number[k+l]
for(l=i-k;l<i;l++)
number[l]=0
//交换后将之前的“1”全部移动到最左端
if(k==i &&
i+1==m-n) //如果第一个“1”已经移动到了m-n的位置,说明
这是最后一个组合了。
end=true
}
if(swap) //交换一次后就不用继续找“10”组合了
break
}
//output()
//屏蔽掉结果输出以节约时间
count++
//组合数计数器递增1
}
printtime()
//打印结束时间
printf("total number of combination is: %d/n",count)
//打印总的组合数
getchar()
}
分析:一个数组,其下标表示1到m个数,数组元素的值为1表示其下标代表的数被选中,为0则没选中。首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。例如求5中选3的组合:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
程序如下:
#include "stdio.h"
#include "time.h"
unsigned char number[100]
//最多求100个数的组合。
unsigned int m,n;// 2<=m<=100,n<m
char tmpbuf[128]
time_t ltime
struct tm *today
void printtime(void) //打印当前时间的函数
{
time(<ime)
today = localtime(<ime )
strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S",today)
printf("%s/n",tmpbuf)
}
void inition() //初始化
{
unsigned int i
for(i=0;i<n;i++)
number=1
}
void output() //输出组合结果
{
unsigned int i
for(i=0;i<m;i++)
if(number)
printf("%02d ",i+1)
printf("/n"
}
void main()
{
unsigned long count
//计数组合个数
unsigned int i,j,k,l
bool findfirst,end,swap
end=false
printf("please input m:"
scanf("%d",&m)
//输入m
printf("please input n:"
scanf("%d",&n)
//输入n
printtime()
//打印开始时间
inition()
//初始化
//output()
//屏蔽掉结果输出以节约时间
count=1
j=m
while(!end)
{
findfirst=false
swap=false
//标志复位
for(i=0;i<j;i++)
{
if(!findfirst &&
number)
{
k=i
//k记录下扫描到的第一个数
findfirst=true
//设置标志
}
if(number &&
!number[i+1]) //从左到右扫描第一个“10”组合
{
number=0
number[i+1]=1
swap=true
//设置交换标志
for(l=0;l<i-k;l++)
number[l]=number[k+l]
for(l=i-k;l<i;l++)
number[l]=0
//交换后将之前的“1”全部移动到最左端
if(k==i &&
i+1==m-n) //如果第一个“1”已经移动到了m-n的位置,说明
这是最后一个组合了。
end=true
}
if(swap) //交换一次后就不用继续找“10”组合了
break
}
//output()
//屏蔽掉结果输出以节约时间
count++
//组合数计数器递增1
}
printtime()
//打印结束时间
printf("total number of combination is: %d/n",count)
//打印总的组合数
getchar()
}