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

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分
能者来拿分!
...全文
82 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
打开链接下载源码: https://pan.quark.cn/s/589796089f72 C++课程设计任务列表,涵盖以下内容:1、识别并显示10至99范围内,各位数乘积超过各位数和的数值,例如数字12不满足条件,因为1乘以2小于1加2,故不输出;而数字27满足条件,因为2乘以7大于2加7,因此需要输出该数。2、开发一个功能,用于从用户输入的任意数量实数中找出最大值与最小值:首先要用户输入一个正整数n,代表数值的个数,随后用户可输入任意n个实数,程序需找出这n个数中的最大值和最小值并将它们展示出来。3、实现两个已排序数组的合并操作:设有数组A和B,且假设这两个数组的元素均已按照降序排列。编写程序将A和B合并成一个新的数组C,并确保C中的元素同样保持降序排列。int A[10]={123, 86,80, 49,33,15,7,0,-1,-3};int B[10]={100,64,51,50,27,19,15,12,5,2};4、设计一个函数,用于计算特定分数序列前n项的总和,该序列为1/2,1/3,1/4,1/5,1/6,1/7,...。要在主程序中提示用户输入一个整数n,并验证输入的合法性(n需大于1方为有效),若输入合法,则调用和函数并显示计算结果。5、编写一个程序,计算两个用户输入日期之间的天数差:用户需以year1,month1,day1和year2,month2,day2的格式输入两个日期,程序随后计算这两个日期之间的天数间隔,并将结果输出到屏幕上。要编制具有如下原型的函数difs2Date:long GetDayDifference(int y1,int m1,int d1,int y2,int m2,int d2);并在主函数中调用此函数,将计...
代码下载地址: https://pan.quark.cn/s/ee8627e4e6d7 ABAP调试器是一种功能强大的工具,可用于在执行期间对ABAP代码进行检验。除了常规的核心功能(例如逐行运行代码以及检验变量、字段符号和引用的值)之外,它还提供了一些辅助性的特性,能够简化并压缩调试会话的时长。并非所有使用者都熟悉这些辅助特性。SAP ABAP调试器是处理和优化ABAP代码开发与维护工作的核心资源,它配备了多样的功能来协助开发人员在运行状态下进行检验和排除故障。此资源着重阐述了ABAP调试器的一些高级特性,涵盖了深入分析调用堆栈、系统级调试、更新会话调试以及提升调试效率的方法。 1. **深入分析调用堆栈**:除了常规的应用程序调试,开发人员有时需要对调用堆栈的内部层级进行深入调试,特别是在错误出现在异步执行的更新处理或系统级程序时。通过启用**系统级调试**,可以访问通常不公开的系统代码,但这也会导致调用堆栈的显著增加,因此需要审慎操作。 2. **系统级调试**:对于不含业务逻辑的系统级程序,开发人员通常无需进行调试。然而,在特定情形下,例如进行错误追踪时,可能需要进入系统代码。借助调试器的“系统调试启用/禁用”选项,可以赋予对系统程序的调试权限。 3. **更新会话调试**:在处理异步更新任务,例如持久化业务数据时,错误可能发生在更新任务内部。激活**更新会话调试**,在更新任务完成后,调试器将自动启动,展示执行路径。比如,在变更成本中心后,通过输入调试指令 "/h" 启动调试,保存后能够看到更新过程中的错误。 4. **分析调用堆栈**:在进行深入调试时,调用堆栈是至关重要的。通过分析调用堆栈,能够定位到引发问题的具体位置,如在VB_V2_NORMAL...

5,943

社区成员

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

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