czcn您好!!有事想请您帮忙,能否把您的信箱地址告诉我? ( 积分: 50 )

  • 主题发起人 主题发起人 sqsq69696
  • 开始时间 开始时间
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&quot

#include "time.h&quot


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,&quot;%Y-%m-%d %H:%M:%S&quot;,today)

printf(&quot;%s/n&quot;,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(&quot;%02d &quot;,i+1)

printf(&quot;/n&quot;)

}

void main()
{
unsigned long count
//计数组合个数
unsigned int i,j,k,l

bool findfirst,end,swap

end=false

printf(&quot;please input m:&quot;)

scanf(&quot;%d&quot;,&amp;m)
//输入m
printf(&quot;please input n:&quot;)

scanf(&quot;%d&quot;,&amp;n)
//输入n
printtime()
//打印开始时间
inition()
//初始化
//output()
//屏蔽掉结果输出以节约时间
count=1

j=m

while(!end)
{
findfirst=false

swap=false
//标志复位
for(i=0;i<j;i++)
{
if(!findfirst &amp;&amp
number)
{
k=i
//k记录下扫描到的第一个数
findfirst=true
//设置标志
}
if(number &amp;&amp
!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 &amp;&amp
i+1==m-n) //如果第一个“1”已经移动到了m-n的位置,说明
这是最后一个组合了。
end=true

}
if(swap) //交换一次后就不用继续找“10”组合了
break

}
//output()
//屏蔽掉结果输出以节约时间
count++
//组合数计数器递增1
}
printtime()
//打印结束时间
printf(&quot;total number of combination is: %d/n&quot;,count)
//打印总的组合数

getchar()

}
 
我是初学DELPHI,对PASCAL语言不熟,想请一位高手帮助把下面这个C++语言有关&quot;从N数中选10的算法&quot;用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 &quot;stdio.h&quot

#include &quot;time.h&quot


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,&quot;%Y-%m-%d %H:%M:%S&quot;,today)

printf(&quot;%s/n&quot;,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(&quot;%02d &quot;,i+1)

printf(&quot;/n&quot;)

}

void main()
{
unsigned long count
//计数组合个数
unsigned int i,j,k,l

bool findfirst,end,swap

end=false

printf(&quot;please input m:&quot;)

scanf(&quot;%d&quot;,&amp;m)
//输入m
printf(&quot;please input n:&quot;)

scanf(&quot;%d&quot;,&amp;n)
//输入n
printtime()
//打印开始时间
inition()
//初始化
//output()
//屏蔽掉结果输出以节约时间
count=1

j=m

while(!end)
{
findfirst=false

swap=false
//标志复位
for(i=0;i<j;i++)
{
if(!findfirst &amp;&amp
number)
{
k=i
//k记录下扫描到的第一个数
findfirst=true
//设置标志
}
if(number &amp;&amp
!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 &amp;&amp
i+1==m-n) //如果第一个“1”已经移动到了m-n的位置,说明
这是最后一个组合了。
end=true

}
if(swap) //交换一次后就不用继续找“10”组合了
break

}
//output()
//屏蔽掉结果输出以节约时间
count++
//组合数计数器递增1
}
printtime()
//打印结束时间
printf(&quot;total number of combination is: %d/n&quot;,count)
//打印总的组合数

getchar()

}
 
也给你相应的控制台程序,程序D7调试通过.
用file->new->other->Console Application创建工程

//程序
program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils,
System;

var
number: array[0..99] of Byte
//最多求100个数的组合。
m, n: Cardinal
// 2<=m<=100,n<m
//tmpbuf: array[0..128] of Byte;
//ltime: TDateTime;
//struct tm *today;

procedure printtime
//打印当前时间的函数
begin
//time(<ime);
//today = localtime(<ime );
//formattmpbuf,128,&quot;%Y-%m-%d %H:%M:%S&quot;,today);
DateSeparator := '-';
ShortDateFormat:='yyyy-mm-dd hh:mm:ss';
Writeln(DateToStr(Now));
end;

procedure inition
//初始化
var
i: Integer;
begin
for i := 0 to n - 1 do
number := 1;
end;

procedure output
//输出组合结果
var
i: Integer;
begin
for i := 0 to m - 1 do
if number = 1 then
write(FormatFloat('00', i + 1));
write(#13#10);
end;

var
count: Longint
//计数组合个数
i, j, k, l: Integer;
findfirst, theend, swap: boolean;
c: char;
begin
theend := false;
write('please input m:');
read(m)
//输入m
write('please input n:');
read(n)
//输入n
printtime
//打印开始时间
inition
//初始化
//output
//屏蔽掉结果输出以节约时间
count := 1;
j := m;
while not theend do
begin
findfirst := false;
swap := false
//标志复位
for i := 0 to j - 1 do
begin
if not findfirst and (number = 1) then
begin
k := i
//k记录下扫描到的第一个数
findfirst := true
//设置标志
end;
if (number = 1) and (number[i+1] <> 1) then //从左到右扫描第一个“10”组合
begin
number := 0;
number[i+1] := 1;
swap := true
//设置交换标志
for l := 0 to i - k - 1 do
number[l] := number[k+l];
for l := i - k to i - 1 do
number[l] := 0
//交换后将之前的“1”全部移动到最左端
if (k = i) and ((i + 1) = (m - n)) then //如果第一个“1”已经移动到了m-n的位置,说明这是最后一个组合了。
theend := true;
end;
if swap then //交换一次后就不用继续找“10”组合了
break;
end;
//output
//屏蔽掉结果输出以节约时间
Inc(count)
//组合数计数器递增1
end;
printtime()
//打印结束时间
write(Format('total number of combination is: %d', [count]))
//打印总的组合数
read(c,c,c)

end.

注:
我忘了C的getchar()取任意字符在delphi应该用什么来代替.所以程序最后,我用了read(c,c,c)来代替.
也就是程序结束后按回车键关闭命令符窗口.
 
czcn的结果好像是错的
(5, 3)的结果是3??

下面的函数,30选10在我p4 2.8下1.063秒计算完毕,总数30045015
当然是不做过程输出了
var
ASelectArray: array[1..128] of Integer;

function Select(ABase: Integer
AChild: Integer): Integer;
var
i, j: Integer;
NeedMoveCount: Integer;
HasMove: Boolean;
s: String;
procedure WriteMemo(AStrings: TStrings);
var
i: Integer;
s: String;
begin
s := '';
for i := 1 to ABase do
begin
s := s + ' ' + IntToStr(ASelectArray);
end;
AStrings.Add(s);
end;

begin
for i := 1 to ABase do
ASelectArray := 0;
Result := 0;

for i := 1 to AChild do
ASelectArray := 1;
Inc(Result);
//WriteMemo(Form1.ListBox1.Items);

HasMove := True;

while HasMove do
begin
HasMove := False
//初始化
for i := 1 to ABase - 1 do
begin
if (ASelectArray = 1) and (ASelectArray[i + 1] = 0) then //需要交换
begin
HasMove := True;
Inc(Result);
ASelectArray := 0;
ASelectArray[i + 1] := 1;
//移动前面的数
//计算需要移动的个数
NeedMoveCount := 0;
for j := 1 to i - 1 do
begin
if ASelectArray[j] = 1 then
Inc(NeedMoveCount);
end;
//移动
for j := 1 to i - 1 do
begin
if j <= NeedMoveCount then
ASelectArray[j] := 1
else
ASelectArray[j] := 0;
end;

//WriteMemo(Form1.ListBox1.Items);

Break;
end;
end;
end;
end;
 
谢谢zealothasu,我的程序确实有错误,翻译后没有测试结果正确与否.

1.下面的一个1打成了0.
if (number = 1) and (number[i+1] <> 0) then //从左到右扫描第一个“10”组合
begin
应为
if (number = 1) and (number[i+1] <> 1) then //从左到右扫描第一个“10”组合
begin
2.所有的for循环,终止值原C是<值,delphi中应要to 值 - 1的,忘了减1

上面的代码已更改.运行结果(Celeron1.3G):
please input m:30
please input n:10
2005-10-25 10:13:07
2005-10-25 10:13:09
total number of combination is: 30045015
 
接受答案了.
 
czcn@163.com
 

Similar threads

I
回复
0
查看
843
import
I
I
回复
0
查看
763
import
I
I
回复
0
查看
573
import
I
后退
顶部