求一排列提取算法,要求能快速的得出结果.

vooder 2005-01-26 05:59:32
现有22组数据,假设如下:
02 03 07 08 14
05 10 12 18 20
05 08 16 19 21
01 07 10 12 20
06 15 19 21 22
01 02 10 12 15
02 03 04 06 13
03 06 07 09 21
02 03 15 19 22
04 05 11 17 19
03 04 10 11 17
07 09 17 20 22
05 08 13 17 20
04 08 14 21 22
06 15 16 18 22
03 10 14 15 17
06 09 10 20 21
01 03 09 16 22
01 15 17 18 20
08 10 11 15 21
09 11 15 19 20
01 02 15 18 19
从上面每组数据中提出一个号来,形成一个排列,排列的要求是:从下一组数据中提出的号不能出现在前面组提出的号所组成的排列;排列的顺序必须按组的顺序排,并且排列中的第一个号必须是第一组中的号,第二个号必须是第二组中的号,以此类推;提号要求是必须从第一组开始提号,排列过程中不跳组,即A、B、C三组,B组中所有的号在前面的排列中都出现了,但C组中有在前面排列未出现的号,还是不能将C组中这个号放入排列中,即不断组取号。
如以上数据可得如下的一个排列:
02 05 08 01 06 10 03 07 15 04 11 09 13 14 16 17 20 22 18 21 19
在这个排列中,从左往右看,02是第一组数据中的一个号;05是第二组数据中的一个号,两个号不同;可以组成排列;到了第三组数据,05虽是第三组数据中的一个号,但在前面两组拿出来的号组成的排列中有05,所以这个05无效,那么就看第三组数据中其它的号,08符合要求,将其加入…………如此取号法,就得到上面的一组排列。

再看下面的一个排列:
07 05 08 01 06 02 03 09 15 04 10 17 13 14 16
到了第16组时发现这一组中所有的号(03 10 14 15 17)在排列中出现了,而第17组中的(20 21)两个号没有在排列中出现,但还是不能将17组中的这两个号任意的一个放入到排列中。那么,这个排列就是最后排列,这也就是不断组排列。

将这22组数据所有满足要求的排列,并且排列的长度大于等于18(即一个排列中至少要有18个号)的都显示出来,同时统计每一个排列中没有出现过的号。望众位高手指点迷津。
...全文
127 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Cipherliu 2005-02-09
  • 打赏
  • 举报
回复
QuickKeyBoard的算法是可行的,在我看来,没有更好的算法了.
不过 QuickKeyBoard在这里用Hash表似乎没有什么用处,这里总共只有22个数,用一个
Selected:Array [1..22] of Boolean来表示每个数是否被选择过就够了.
这里关于Hash表的操作有点小题大做了.
chinaandys 2005-01-29
  • 打赏
  • 举报
回复
学习
QuickKeyBoard 2005-01-29
  • 打赏
  • 举报
回复
这样做:delphi7 windowsxpsp2下通过
逐层搜索所有可行解,实则输出。
我加了一个Hash来优化运算,但还是很慢,搂住自己去等吧。

program Select;
{$APPTYPE CONSOLE}

var
Data: array [1..22, 1..5] of integer;
Hash: array [0..99] of Boolean;
Sel: array [1..22] of Integer;

procedure WriteOut(n: Integer);
var
i: Integer;
begin
for i := 1 to n do
Write( Sel[i]:3);
Writeln;
Write('The code out of queue:');
for i := 1 to 22 do
if Hash[i] = False then
Write(i:3);
Writeln;
end;

procedure ReadData;
var
f: TextFile;
i, j: Integer;
begin
FillChar(Hash, 100 * SizeOf(Boolean), 0);
FillChar(Sel, 22 * SizeOf(Integer), 0);
AssignFile(f, 'data.txt');
Reset(f);
for i := 1 to 22 do
for j := 1 to 5 do
Read(f, Data[i, j]);
CloseFile(f);
end;

procedure Search(step: Integer);
var
j: Integer;
begin
if step > 22 then
Exit;

if step > 18 then
begin
WriteOut(step - 1);
Exit;
end;

for j := 1 to 5 do
if Hash[Data[step, j]] = False then
begin
Hash[Data[step, j]] := True;
Sel[step] := Data[step, j];
Search(step + 1);
Hash[Data[step, j]] := False;
end;
end;

begin
ReadData;
Search(1);
end.

vooder 2005-01-29
  • 打赏
  • 举报
回复
自己也写了一个,也是逐层搜索.说实在的,速度还真的是慢,没办法.我想问的是有没有通过其它的方法先判断出当哪一组有哪一个号时,就不可能出现排列的长度大于18.这样的话就可以省下很多了.
fsybaby 2005-01-28
  • 打赏
  • 举报
回复
深度优先搜索?
定义一个集合,然后逐层推,直到推出合适的路径.不过效率很低
vooder 2005-01-26
  • 打赏
  • 举报
回复
自己先来顶一下,希望得到高手的指点。

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧