100分继续挑战算法高手(50分求购算法的续集)up有分 (100分)

  • 主题发起人 主题发起人 快刀不快
  • 开始时间 开始时间

快刀不快

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠,我的问题的前半部分已经解决,请参考(50分求购算法)中form2和jsxjd的代码。
我的问题如下:在算出一个n×n的随机序列之后(每一行,每一列都不重复)如:
3 2 4 1 5
1 5 2 4 3
2 1 3 5 4
4 3 5 2 1
5 4 1 3 2
现在我要求第2个n*n(该例就是5*5)的序列,第二个方阵的每个数字与第一个方阵的每个
数字相遇1次,而且仅仅1次。如以下2个序列就满足该条件。
第一个 第2个
1 2 3 4 5 1 2 3 4 5
2 3 4 5 1 3 4 5 1 2
3 4 5 1 2 5 1 2 3 4
4 5 1 2 3 2 3 4 5 1
5 1 2 3 4 4 5 1 2 3
但是提醒各位注意,我的排列没有这么简单。这个例子只是为了说明要求而已。
切记:第一个系列要求是随机的(算法可参考“50分求购算法”)。要求出满足要求的第2个方阵。
 
注意8*8太慢了
加:
var
k1:array[1..x,1..x]of byte;
tmp:tstringlist;
.......
procedure TForm1.FormCreate(Sender: TObject);
begin
......
tmp:=tstringlist.create;
end;

procedure cls_k1;
var
a,b:byte;
begin
for a:=1 to xdo
for b:=1 to xdo
k1[a,b]:=0;
end;

procedure SavetoK1;
var
a,b:byte;
begin
for a:=1 to xdo
for b:=1 to xdo
k1[a,b]:=k[a,b];
end;

procedure TForm1.Button2Click(Sender: TObject);
var
a,b,c:byte;
s:string;
z:array[1..x]of byte;
procedure clsz;
var
a:byte;
begin
for a:=1 to xdo
z[a]:=0;
end;
function askz:byte;
var
a:byte;
begin
result:=0;
for a:=1 to xdo
if z[a]=1 then
result:=result+1;
end;
procedure wm2(n:byte);
var
a,b:byte;
begin
for a:=1 to xdo
begin
s:='';
for b:=1 to xdo
begin
if n=1 then
s:=s+inttostr(k1[a,b])+',' else
s:=s+inttostr(k[a,b])+',';
end;
tmp.Add(copy(s,1,length(s)-1));
end;
tmp.Add('');
end;
label xx;
begin
memo2.clear;tmp.clear;
Application.ProcessMessages;
cls_k;cls_k1;Get_k1;SavetoK1;
while truedo
begin
xx:
cls_k;clsz;Get_k1;
for a:=1 to xdo
for b:=1 to xdo
begin
if k1[a,b]=k[a,b] then
begin
if z[k1[a,b]]=0 then
z[k1[a,b]]:=1 else
goto xx;
end;
if askz=x then
break;
end;
if askz=x then
break;
end;
wm2(1);wm2(2);
memo2.lines:=tmp;
end;
 
总觉得fom2的方法过程太多了,显得很复杂,而且有一点乱。还是jsxjd的方法简单明了些。
不知道各位怎么看。最好把上次的代码和这次的一起帖出来,省得到处找。
我up。呵呵
 
form2,你的循环不行,出不去。
up有分。
 
呵呵,没错,我昨晚只测试了3-7,8*8今天回家,运算了一下,4分多钟才得出结果
4,5,2,6,1,3,7,8
8,1,7,5,3,2,4,6
7,6,8,3,2,4,5,1
2,7,3,1,5,8,6,4
6,2,5,7,4,1,8,3
5,3,1,4,8,6,2,7
1,4,6,8,7,5,3,2
3,8,4,2,6,7,1,5
8,7,4,2,5,6,3,1
7,1,2,6,4,3,5,8
5,8,7,4,1,2,6,3
6,2,1,7,3,5,8,4
1,4,5,3,6,8,7,2
4,3,8,5,7,1,2,6
3,5,6,8,2,4,1,7
2,6,3,1,8,7,4,5
不过3-6挺快的,程序逻辑本身没有错误,只是用这种方法延续你这贴的要求,
从上一贴开始就是错的。jsxjd的代码不错,我的是真模糊,他的是假模糊而已
 
form2这种算法挺慢的,能不能优化一下。另外前半部分你能不能用一下jsxjd的方法。
我较喜欢他的代码。我有可能要用到20*20的啊
 
老大,您完全可以编辑您的问题贴,将其放在“数据结构”分类——这明明是算法问题嘛。
 
对于n*n的每行每列都没有相同数字的第一个矩阵,第二个方阵的每个数字与第一个方阵的
每个数字相遇1次,而且仅仅1次,很简单的方法如下:
0。假设第一个矩阵为M1[i,j],第二个矩阵为M2[i,j],下标从1~n
1。完全拷贝一列,M2[i,1]:=M1[i,1],i=1~n
2。如果n是奇数,将M1每行下标从2到n的数字相邻两个进行对换
对于第m行,M2[m,2*i]:=M1[m,2*i+1];
M2[m,2*i+1]:=M1[m,2*i];
3。如果n是偶数,对于每行下标从2到n-3的偶数个数字进行类似2的变换
对于每行最后三个数,M2[m,n-2]:=M1[m,n-1];M2[m,n-1]:=M1[m,n];M2[m,n]:=M1[m,n-2];
4。由于对M1只进行了行内数字位置对换,所以M2每行数字没有重复
由于对M1每行数字位置变换的方法相同,所以M2每列数字也没有重复
5。由步骤1知M1和M2只有第一列相同,第一列包含了n个不同数字,所以n个不同数字在
第一列相遇各一次;由步骤2和3知所有行都没有重复数字
6。其实这只不过是一个满足题目要求的简单的矩阵列变换而已,大家看见类似题目
的时候不要只想到去编程,去搜索,其实只是一个很简单的数学问题啦
 
多人接受答案了。
 

Similar threads

D
回复
0
查看
832
DelphiTeacher的专栏
D
后退
顶部