返回列表 发帖
奇数阶幻方的构造方法(楼梯法)。
把1(或最小的数)放在第一行正中;
按以下规律排列剩下的n*n-1个数:
  1)每一个数放在前一个数的右上一格;
  2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
  3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
  4)如果这个数所要放的格已经超出了顶行且超出了最右列那么就把它放在前一个数的下一行同一列的格内;
  5)如果这个数所要放的格已经有数填入,处理方法同4)。
  1. @echo off
  2. :start
  3. setlocal enabledelayedexpansion
  4. echo.&set /p n= 请输入一个奇数 &cls
  5. set /a m=n/2+1,h=1,c=n*n,he=(n*n+1)*n/2
  6. echo  !n! 阶幻方各行,列以及对角线相加的和为: %he%&echo.
  7. set .1-!m!=1
  8. for /l %%a in (2 1 !c!) do call :loop %%a
  9. for /l %%a in (0 1 9) do set c=!c:%%a= %%a !
  10. for %%a in (!c!) do set /a j+=1
  11. for /l %%a in (1 1 !n!) do (
  12.    set "num="
  13.    for /l %%b in (1 1 !n!) do (
  14.       set "var=                                !.%%a-%%b!"
  15.       set "num=!num! !var:~-%j%!"
  16. )
  17.    echo.!num!
  18. )
  19. endlocal&goto start
  20. :loop
  21.    set /a h-=1,m+=1
  22.    if !h! lss 1 set /a h=n
  23.    if !M! gtr !n! set /a m=1
  24.    if defined .!h!-!m! (
  25.       if !qh! equ !n! (set /a h=2) else set /a h=qh+2
  26.    set /a qh=h-1,m=qm-1
  27.    goto loop
  28. )
  29.    set ".!h!-!m!=%~1"
  30.    set /a qh=h,qm=m
  31. goto :EOF
复制代码

[ 本帖最后由 随风 于 2009-4-3 10:46 编辑 ]
1

评分人数

    • lhjoanna: 好,能否考虑再提升下效率~PB + 8
技术问题请到论坛发帖求助!

TOP

回复 18楼 的帖子

不懂什么是一维变量,代码一写好就发现效率是个大问题,一直没有办法解决,这种幻方构造方法是临时在网上找的,lhjoanna兄是否还有更好的算法?拿来分享一下。又或者我的代码还可以如何改进,请指点。。
技术问题请到论坛发帖求助!

TOP

仔细琢磨了兄的代码。效率及算法都比我的强多了。
最不懂的一句 set /a "loc=n*(i-1)+j" 应该也是精华吧。
不过有一处不太明白,好像也不太容易说明白。举个例吧
a    1    c
3    e    f
g    h    2
此时 4 应该放在 b 的位置,也就是 1 的位置,但位置被 1 占了,
所以 4 就应该放在前一个数的下一行同一列的格内,也就是 g 位,
问题来了,不知道幻方会不会有这种情况出现,就是 g 位此时也已经被别的数占了,
如果这种情况存在,那么按我的理解就应该放在g的下面。
同样,如果存在这种情况,那么兄的代码似乎没对这种反复的情况作处理啊。
技术问题请到论坛发帖求助!

TOP

回复 22 楼 lhjoanna 兄

多谢兄的耐心讲解,认真看了看,说实话但也只看懂个大概,不过也受益匪浅了。
既然不存在目标数的下一行对应的数被占用的情况,那么代码可以修改一下提高效率。
我17楼代码之所以效率低下应该是因为call太多,loop就是为了处理这种情况,现在看来是多余的。
:
  1. @echo off
  2. :start
  3. setlocal enabledelayedexpansion
  4. echo.&set /p n= 请输入一个奇数 &cls
  5. set /a m=n/2+1,h=1,c=n*n,he=(n*n+1)*n/2
  6. echo  !n! 阶幻方各行,列以及对角线相加的和为: %he%&echo.
  7. set .1-!m!=1
  8. for /l %%a in (2 1 !c!) do (
  9.    set /a h-=1,m=m%%n+1
  10.    if !h! equ 0 set /a h=n
  11.    if defined .!h!-!m! set /a h=qh%%n+1,m=qm
  12.    set ".!h!-!m!=%%a"
  13.    set /a qh=h,qm=m
  14. )
  15. for /l %%a in (0 1 9) do set c=!c:%%a= %%a !
  16. for %%a in (!c!) do set /a j+=1
  17. for /l %%a in (1 1 !n!) do (
  18.    set "num="
  19.    for /l %%b in (1 1 !n!) do (
  20.       set "var=               !.%%a-%%b!"
  21.       set "num=!num! !var:~-%j%!"
  22.     )
  23.     echo.!num!
  24. )
  25. endlocal&goto start
复制代码
2

评分人数

技术问题请到论坛发帖求助!

TOP

想通过代码来了解算法太难了,大致看了下兄的代码流程,只发现一处影响代码效率的地方。
批处理的运行效率,个人认为 set 或 set /a 并不会太影响,关键是看代码的设计,for的循环次数尤其是嵌套循环,再就是call若在for循环中有call则一定会使效率大打折扣。
建议改进的地方:
:exchange 标签下
call set _%%i%%j=%%_!i!%%j%%
改为 for %%a in (!i!) do set _%%i%%j=!_%%a%%j!
技术问题请到论坛发帖求助!

TOP

返回列表