高分求一个妙解(经典算法问题)!

leejidongdong 2003-04-12 06:08:06
一个3*3的格子(即9个格子),每个格子可以放一个数字,数字在1-9之间任取,每个格子里面放一个数字而且各不相同,求:每一行的和等于每一列的和且等于每条对角线的和这种组合方式,并打印出来。(Pascal语言实现)

例如如下这个组合:

6 | 1 | 8
-----------------
7 | 5 | 3
-----------------
2 | 9 | 4

谢谢!

注:重在巧妙。按其排名前4名的有分。
第一名:50分
第二名:30分
第三名:15分
第四名: 5分
能者来拿分!
...全文
38 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
AWolfBoy 2003-04-18
  • 打赏
  • 举报
回复
没时间写,本来原先还用写过一个,可以列举所用的可能排列。
数据结构确实是个不错的东西,有空你可以看一下组合数学和图论的算法与设计,还有实用算法与设计,都是很不错的。
leejidongdong 2003-04-18
  • 打赏
  • 举报
回复
以作者的一点愚见,作者写了一个比较笨的程序,将所有可能的排列全列出来再逐个判断。也许不是那么巧妙,但是一定不会漏解(共8组),不过只适用于3阶幻方。下面就是本人的程序。(用递归和回溯来实现)

{********************************************************************}
program cube;
var
i: integer;
j: integer;

b:array[1..9] of integer;

f:array[1..9,1..2] of integer;

procedure init;
var
i,j:integer;
begin
for i:=1 to 9 do b[i]:=0;

for i:=1 to 9 do
begin
f[i,1]:=i;
f[i,2]:=0;
end;


end;


procedure layall(N: integer);

var
i: integer;
j: integer;
m: integer;
h1: integer;
h2: integer;
h3: integer;
h4: integer;
h5: integer;
h6: integer;
h7: integer;
h8: integer;
count: integer;
lie:integer;



begin
j:=1;
count:=0;
while (1<=j)and(j<=9) do
begin
if (f[j,2]=0) then
begin
b[N] := f[j,1];
count := count +1;
f[j,2]:= 1;
if (N>1) then
begin
layall(N-1);
f[j,2]:=0;
j:=j+1;
if j>9 then
begin
exit;{}
end;
end
else
begin
h1 := b[1] + b[2] + b[3];
h2 := b[4] + b[5] + b[6];
h3 := b[7] + b[8] + b[9];
h4 := b[1] + b[4] + b[7];
h5 := b[2] + b[5] + b[8];
h6 := b[3] + b[6] + b[9];
h7 := b[1] + b[5] + b[9];
h8 := b[3] + b[5] + b[7];
if ((h1=h2)and(h2=h3)and(h3=h4)and(h4=h5)and(h5=h6)and(h6=h7)and(h7=h8)) then
{if (true) then}
begin
writeln('equal');
lie:=0;
for m:=1 to 9 do
begin
if lie<3 then
begin
write(b[m]);
write(' ');
lie:=lie+1;
end
else
begin
lie:=1;
writeln;
write(b[m]);
write(' ');
end;


end;
writeln;
f[j,2]:=0;

end
else
begin
f[j,2]:=0;


end;
exit;{exit to the circle}
end;
end
else
begin
if count=N then
begin
count:=0;
exit;
end
else
begin
if (j<9) then
begin
j:=j+1;


end
else
begin
j:=1;
end;
end;
end;
end;
end;


begin
init;
writeln('program begin');
layall(9);
end.
leejidongdong 2003-04-18
  • 打赏
  • 举报
回复
AWolfBoy(龍行江湖) 程序中还有些小错误,不过我改了一下,可以运行了。
不过很抱歉的说,当我输入n=3时,你的程序只给出了下面这样一个解。
8 | 3 | 4
2 | 6 | 7
5 | 9 | 1
呵呵,这个解显然是不对的。
jpyc 2003-04-15
  • 打赏
  • 举报
回复
有意思,观望
AWolfBoy 2003-04-15
  • 打赏
  • 举报
回复
这不就是魔方算法吗。而且是没有1,2,6阶魔方的成立。
下面是一个纯Pascal(不是在Delphi下) 给出的魔方算法。
Program MOFANG;
uses crt;
const Maxn =100;
type
listtype : array[0..Maxn,0..Maxn] of integer;
var
list : listtype;
n : integer;
procedure init;
begin
clrscr;
repeat write('n=');
readln(n);
until (n>0) and (n<Maxn) and (odd(n));
end;

procedure main;
var
i, j, x, y;
begin
fillchar(list, sizeof(list),0);
x :=0; y := n div 2;
for i := 0 to n-1 do
begin
for j := 0 to n do
begin
list[x,y] := i*n + j;
x := (n+x-1) mod n;
y := (y + 1) mod n;
end;
x := (x + 2) mod n;
y := (n+y-1) mod n ;
end;
end;
procedure Show;
var
i, j : integer;
begin
for i := 0 to n-1 do
begin
for j := 0 to n-1 do
write(list[i,j]:3);
writeln;
end;
end;
begin
init;
main;
show;
end;



love4myxsg 2003-04-15
  • 打赏
  • 举报
回复
不是我不关注算法,不过是目前看来实在不明白有什么用处。。。。哭...
liaoqingpeng 2003-04-14
  • 打赏
  • 举报
回复
有一个算法:斜左上角算法吧(也许名字不对),在谭浩强的VB那本书里有。
短歌如风 2003-04-14
  • 打赏
  • 举报
回复
qhgary(Shining) 说的就是最传统的数字方阵的解法啊,时间 为O(n)你还嫌不巧妙?这种方法可以说是中华文化传统中的精华(之一)啊!
leejidongdong 2003-04-14
  • 打赏
  • 举报
回复
不能怪我不给分,而是大家都没有什么好的算法出来,呵呵
qhgary 2003-04-12
  • 打赏
  • 举报
回复
如果是求全部解并且把旋转,反转得到的均算成不同的话。也很容易
穷举好了(但是如果阶数大了就不行,而且效率不高)
如果要求解均不相同,就是经变化都不能变到一样才叫不同解的话,也不难,在穷举的时候不要全部穷举,做些筛选就行。
如果要求阶数任意(可能很大)并且要求求出全部不同解,且每组解变化后都不会相同。好象没有什么好用的方法。。。
qhgary 2003-04-12
  • 打赏
  • 举报
回复
如果只要求一组解而不是全部的话,其实很简单。
其实下面的方法适合所有奇数阶
1.将1放到第一行正中间
2.将2放到1的右上角
3.将3放到2的右上角
。。。
可能碰到这样的情况,右上角出界了,比如填2时候,没有关系哪个坐标出界则对你的阶数n取模,如果为负就加上n。
还可能碰到右上角已经有数字了,那么就放到自己的正下方。比如3右上角已经放了1,则4就放到它的正下方。
下面是个例子
8 1 6
3 5 7
4 9 2
love4myxsg 2003-04-12
  • 打赏
  • 举报
回复
第四名: 5分...(高分-_-;)
怎么算巧妙啊。
是不是电脑计算次数少就算巧啊。。。
如果那样,实现定义幻方,然后查表。。。。几乎没有计算过程。。。呵呵。
如果必须要实现幻方的计算。。。。。。。。
这个只3层,中间一定是5。。。。(不要问我为什么。。。怎么可能不是啊?)
然后2边能插入的一定是奇数对奇数,偶数对偶数,否则不对称。。。
至于奇数4个放在4角还是边上。。。。。。。。
假设排除法吧:

假设奇数在角上:
因为有中间一定是5。。。。所以如果奇数要在角,则对角线最后只能是奇数
因为2个奇数+5=奇数,
但是行或者列都是2个奇数+中间一个偶数=偶数。。。。。。。
矛盾

所以命题不成立。==〉奇数该放在边上。。。。。。。。。
得解。。。。。。。。。。


没工夫写代码咯。hohoho
dreamonce 2003-04-12
  • 打赏
  • 举报
回复
我记得中间的必须是5,我想要实现没什么困难的.
rustle 2003-04-12
  • 打赏
  • 举报
回复
gz
alphax 2003-04-12
  • 打赏
  • 举报
回复
mark

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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