[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
呵,我上面写的一些也只是自己的猜测而已,没有一些理论的支持。说实话,我之前对兄的那段loop循环也是一知半解,不过现在明白了,这样修改以后效率提高很多啊,比我的效率也要高一点。这也就说明了我对于一维变量提高效率的说法是不准确的。看来还要自己多研究,不能仅凭想法臆断!多谢兄~

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

要存储n^2个数,就要建立n^2个变量,我是用.1-.n^2来表示这n^2个数的,所以set /a "loc=n*(i-1)+j这句也就是计算当前的数在幻方整个n^2个数中的位置。这样也就代替了用.%%a%%b构建行、列的情况。
     兄说到的那个问题,我想这种情况是不可能出现的,目标数的下一行对应的数不可能被占用。我想数学家罗伯在构思这种幻方构造法时如果发现目标数下一行对应的数会出现被占用的可能,那么在构造规则中就会声明这种情况的处理办法了。我仔细观察了19阶幻方,用此法构建确实不会出现上述情况,可能数学能力有限,我很难用数学语言严谨的表达出来。不过设想下19阶幻方第一行与最后一行相接,第一列与最后一列相接,会出现一个球,那么从1开始连线,你会发现1-19的连线划过的区域是此球最大的圆周,并且假设单位为1,则此圆的周长就是19单位,而此连线只经过了18单位,因为在继续到第19单位时,此位置已经有1占了。所以转到第二个圆周,此第二个圆周与第一个圆周之间的夹角为(360/19)°,这样连续转19次,也就满了360°,即画了19个最大圆,并且每个圆都是不封闭的,每个圆都不相交(因为每将要到相交的地方,就会跳到下一个圆周),这样看来下一个圆周的第一个位置是永远不会被占的。拿19阶幻方为例,从1-361相连,你会发现是一条不间断的空间曲线,并且361的下一个就是1。361与1衔接,成功的构造了一个球体。只是这个球体的表面是不光滑的,有间隔的凹陷。在此构造过程中,幻方的各个元素在逆时针旋转,而构成的圆周(纵向来看)是顺时针转动的。由此猜想:抛开球体看,只看1-n^2的连线,阶数越高,此连线也接近球体。既然如此接近球体,那么此曲线的方程(坐标由幻方的各个元素构成)和球体的方程(x-a)²+(y-b)²+(z-c)²=R²有千丝万缕的联系。又一猜想:说不定幻方的方程(猜测:f(x,y,z)=n²)当n(阶数)趋于无穷时,幻方的方程也就等于球的方程(或类球方程)。
     呵,大晚上的容易乱想,想了一堆,还没有在网上找到类似支持的理论,只做一种猜测吧!
1

评分人数

    • BBCC: 听君一言,胜读十年书! + 1 技术 + 1 PB + 8

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

呵,指点谈不上,说讨论更贴切些~~说实话,一维变量是我编出来的,官方没有这样的说法,举个例子,类似.%%a%%b我称它为二维的,而对比下 .%%a就是一维了。感觉这样说简炼些^_^
        我的算法也就是兄所说的楼梯法,更确切些叫罗伯法。这是目前比较容易的构造方法了。我也一直在思考效率的提高问题,在目前的这个算法下,我也只想到把变量改为一维(暂称)的可以提高一些效率,我的代码在下面,还请兄帮忙测试或者改进下!
  1. @echo off
  2. :begin
  3. setlocal enabledelayedexpansion
  4. color 0c
  5. cls
  6. echo.&echo  本程序功能为输出n阶幻方!
  7. echo.&echo  所谓n阶幻方:1-n^^2个数排为n行n列;
  8. echo.&echo  要求:横、竖、对角线相加和相同。
  9. echo.&echo  算法:loubere法
  10. echo.&set /p "n= 请输入方阵阶数(奇数):"
  11. echo !n!|findstr "^[1-9]*$">nul || (echo.& echo  Non-Numberic & pause>nul & goto begin)
  12. set /a a=n%%2
  13. if !a! equ 0 echo.&echo  Non-Odd & pause>nul & goto begin
  14. cls
  15. echo.&echo %time%
  16. set /a "sum=(1+n*n)*n/2"
  17. echo.&echo  !n!阶幻方横、竖、对角线相加和为 !sum!
  18. echo.
  19. set /a square=n*n,i=1,j=(n+1)/2,loc=j
  20. set ".!loc!=1"
  21. for /l %%i in (2 1 !square!) do (
  22.      set /a "i=(i-1)%%n,j=(j+1)%%n"
  23.      if !i! equ 0 set /a i=n
  24.      if !j! equ 0 set /a j=n
  25.      set /a "loc=n*(i-1)+j"
  26.      if defined .!loc! (
  27.          set /a "i=(i+2)%%!n!,j=(j-1)%%n"  
  28.          if !i! equ 0 set /a i=n
  29.          if !j! equ 0 set /a j=n
  30.          set /a "loc=n*(i-1)+j"
  31.      )
  32.      set .!loc!=%%i
  33.   rem echo  i:!i!,j:!j!,loc:!loc!,.loc:%%i
  34. )
  35. call :unify
  36. for /l %%i in (1 1 !square!) do (
  37.      set /a "c=%%i%%n"
  38.      set "result=!result! !.%%i!"
  39.      if !c! equ 0 echo !result!&set "result="
  40. )
  41. echo.&echo %time%&echo.
  42. pause>nul&endlocal&goto begin
  43. :unify
  44. for /l %%i in (1 1 !square!) do (
  45.      if !.%%i! lss 10 set ".%%i= !.%%i!"
  46.      if !n! gtr 10  (
  47.         if !.%%i! lss 100 ( set ".%%i= !.%%i!")
  48.      )
  49. )
  50. goto :eof
复制代码

TOP

回复 18楼 的帖子

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

TOP

Re:随风
     从兄的代码中又学了不少,变量清空操作只需要endlocal就可以代替几行语句;并且输出时赋值给变量,按行输出确实比按个输出节省了不少时间(特别是阶数很高的情况下);兄能否考虑下用一维的变量来实现,这应该也是提升效率的一个方法。

TOP

奇数阶幻方的构造方法(楼梯法)。
把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

Re:more
      呵,结果是可以对齐了,只是代码是不是繁了点。不需要在赋值的过程中多次调用duiqi,可以在赋值完毕后统一调整格式(包括1)。
   在兄11楼代码基础上修改:
  1. @echo off&setlocal enabledelayedexpansion
  2. :bgn
  3. echo.&set input=&set /p input=请输入一个单数(回车退出):
  4. if not defined input goto :eof
  5. cls
  6. echo %time%&echo.
  7. echo.%input%|findstr /v "^[0-9]*$" >nul&&(echo.请输入纯数字!!!&goto :bgn)
  8. echo.%input:~-1%|findstr "[^13579]" >nul&&(echo.请输入单数...&goto :bgn)
  9. set /a num1=(%input%*%input%+1)*%input%/2,num2=%input%*%input%
  10. echo.%input%阶幻方各行,列以及对角线相加的和为:%num1%
  11. set /a lie=%input%/2+1,hang=1,all=1
  12. set h1l%lie%=1
  13. :agn
  14. set /a hang-=1,lie+=1,all+=1
  15. if %hang% lss 1 set hang=%input%
  16. if %lie% gtr %input% set lie=1
  17. if defined h%hang%l%lie% (set /a hang+=2,lie-=1)
  18. set h%hang%l%lie%=%all%
  19. if "%hang%"=="1" (
  20.    if "%lie%"=="%input%" (
  21.      set /a hang+=1,all+=1
  22.      call set h%%hang%%l%lie%=%%all%%
  23.    )
  24. )
  25. if %all% geq %num2% goto :show
  26. goto :agn
  27. :show
  28. call :duiqi
  29. echo.
  30. for /l %%a in (1 1 %input%) do (
  31.   for /l %%b in (1 1 %input%) do (
  32.     call set/p=%%h%%al%%b%% <nul
  33.     set "h%%al%%b="
  34.   )
  35.   echo.
  36. )
  37. echo %time%&echo.
  38. goto :bgn
  39. :duiqi
  40. for /l %%a in (1 1 !input!) do (
  41.   for /l %%b in (1 1 !input!) do (
  42.    if !h%%al%%b! lss 10 set "h%%al%%b= !h%%al%%b!"
  43.    if !input! gtr 10  (
  44.         if !h%%al%%b! lss 100 ( set "h%%al%%b= !h%%al%%b!")
  45.    )
  46.   )
  47. )
复制代码
附:一点改进的建议
   1、可以考虑不用二维变量来实现,直接用一维变量即可。即h%hang%l%lie%可以用类似h%var%来实现;这样做的好处有:1>精简代码,方便调试;2>提高效率,使用二维变量,在输出时就要2个for嵌套,时间复杂度会达到平方级,且变量的设立与空间分配也要多出一倍。
    2、我用19阶幻方输出做为测试。二维变量的情况下运行时间为1.3~1.4s,而一维变量的情况下只需要0.4~0.5s。虽然不同机子上时间不相同,但同一台机子上,同种情况下的对比结果还是能说明一些问题的。

[ 本帖最后由 lhjoanna 于 2009-4-2 20:44 编辑 ]
1

评分人数

TOP

兄弟不才,用了其它语言

我用pascal,批处理写不出来,一急就用其它高级语言了,不过这一题是初中生的竞赛题。

[ 本帖最后由 tyc 于 2009-4-3 07:34 编辑 ]

TOP

应版主的要求,再做一些修改吧:
  1. @echo off
  2. :bgn
  3. set input=&set /p input=请输入一个单数(回车退出):&cls
  4. if not defined input goto :eof
  5. echo.%input%|findstr /v "^[0-9]*$" >nul&&(echo.请输入纯数字!!!&goto :bgn)
  6. echo.%input:~-1%|findstr "[^13579]" >nul&&(echo.请输入单数!!!&goto :bgn)
  7. set /a num1=(%input%*%input%+1)*%input%/2,num2=%input%*%input%
  8. echo.%input%阶幻方各行,列以及对角线相加的和为:%num1%&echo.
  9. set /a lie=%input%/2+1,hang=1,all=1
  10. if %num2% gtr 99 (set h1l%lie%=  1) else (set h%hang%l%lie%= 1)
  11. :agn
  12. set /a hang-=1,lie+=1,all+=1
  13. if %hang% lss 1 set hang=%input%
  14. if %lie% gtr %input% set lie=1
  15. if defined h%hang%l%lie% (set /a hang+=2,lie-=1)
  16. call :duiqi
  17. if "%hang%"=="1" (
  18.   if "%lie%"=="%input%" (
  19.     set /a hang+=1,all+=1
  20.     call :duiqi
  21.   )
  22. )
  23. if %all% geq %num2% goto :show
  24. goto :agn
  25. :show
  26. for /l %%a in (1 1 %input%) do (
  27.   for /l %%b in (1 1 %input%) do (
  28.     call set/p=%%h%%al%%b%%  <nul
  29.     set "h%%al%%b="
  30.   )
  31.   echo.&echo.
  32. )
  33. goto :bgn
  34. :duiqi
  35. if %num2% gtr 99 (
  36.   if %all% lss 10 (
  37.     set h%hang%l%lie%=  %all%
  38.   ) else (
  39.     if %all% lss 100 (
  40.       set h%hang%l%lie%= %all%
  41.     ) else (
  42.       set h%hang%l%lie%=%all%
  43.     )
  44.   )
  45. ) else (
  46.   if %num2% gtr 9 (
  47.     if %all% lss 10 (
  48.       set h%hang%l%lie%= %all%
  49.     ) else (
  50.       set h%hang%l%lie%=%all%
  51.     )
  52.   ) else (set h%hang%l%lie%= %all%)
  53. )
复制代码

TOP

Re:more
      结果符合幻方的要求,代码也不错,在此基础上提些小建议(供参考):
   1、对于大于3的要求我觉得不必,因为1阶幻方也是幻方,只不过所含的元素只有一个而已,可以统一起来考虑;
   2、对于输入的限制,兄所用的方法是判断最后一位是否奇数,对于要求不高的情况可以满足,但如果要求苛刻些,比如输入a3、12a5等情况,可能会出错。最好还是用完全匹配来限制输入;
   3、对于算法的实现,我没有仔细的验证,应该没问题,毕竟结果正确,并且也符合了行++,列- -,到边的话首尾相接,元素已存在的话放到正下方 等规则;
   4、输出结果正确,再加上对齐就完美了。^_^

Re:tyc
      不知兄用的什么语言,我还真没用过,不过我基本看懂了,一些语法的问题我就无从知晓了,不过算法是正确的。其实对于输出幻方来说,实现起来这样的高级语言比批处理容易些,因为数组类型是内置的,而批处理则需要自己构建一个类似的二维数组来方便操作;此题要求是用批处理来实现,所以希望兄闲暇时也考虑下用批处理来实现~不管怎么说,毕竟动了一番脑子,加分鼓励^_^

TOP

我试试,化了一节课的时间才做出来的

  1. program aa;
  2. var
  3. i,j,m,n:integer;
  4. a:array [1..100,1..100] of integer;
  5. begin
  6. repeat
  7. readln(n);
  8. m:=n mod 2;
  9. until m<>0;
  10. for i:=1 to n do
  11.   for j:=1 to n do a[i][j]:=0;
  12. i:=2;j:=n div 2;
  13. for m:=1 to n*n do
  14. begin
  15.   i:=i-1;j:=j+1;
  16.   if (i=0) and (j<>n+1) then  i:=n;
  17.   if (j=n+1) and (i<>0) then j:=1;
  18.   if (a[i][j]<>0) or (i=0) and (j=n+1) then
  19.   begin
  20.     i:=i+2;
  21.     j:=j-1;
  22.   end;
  23.   a[i][j]:=m;
  24. end;
  25. for i:=1 to n do
  26.   begin
  27.   for j:=1 to n do
  28.    write(a[i][j]:5);
  29.   writeln;
  30.   end;
  31. end.
复制代码

[ 本帖最后由 tyc 于 2009-4-2 16:20 编辑 ]
1

评分人数

    • lhjoanna: 希望也能用批来实现~PB + 5

TOP

试试:
  1. @echo off
  2. :bgn
  3. set input=&set /p input=请输入3以上的单数(回车退出):
  4. if not defined input goto :eof
  5. cls
  6. if %input% lss 3 (echo.你输入的也太小了吧...&goto :bgn)
  7. echo.%input:~-1%|findstr "[^13579]" >nul&&(echo.请输入单数...&goto :bgn)
  8. set /a num1=(%input%*%input%+1)*%input%/2,num2=%input%*%input%
  9. echo.%input%阶幻方各行,列以及对角线相加的和为:%num1%
  10. set /a lie=%input%/2+1,hang=1,all=1
  11. set h1l%lie%=1
  12. :agn
  13. set /a hang-=1,lie+=1,all+=1
  14. if %hang% lss 1 set hang=%input%
  15. if %lie% gtr %input% set lie=1
  16. if defined h%hang%l%lie% (set /a hang+=2,lie-=1)
  17. set h%hang%l%lie%=%all%
  18. if "%hang%"=="1" (
  19.   if "%lie%"=="%input%" (
  20.     set /a hang+=1,all+=1
  21.     call set h%%hang%%l%lie%=%%all%%
  22.   )
  23. )
  24. if %all% equ %num2% goto :show
  25. goto :agn
  26. :show
  27. for /l %%a in (1 1 %input%) do (
  28.   for /l %%b in (1 1 %input%) do (
  29.     call set/p=%%h%%al%%b%%  <nul
  30.     set "h%%al%%b="
  31.   )
  32.   echo.
  33. )
  34. goto :bgn
复制代码
2

评分人数

TOP

呵,我发现什么帖子都逃不过batcher的眼睛啊~此链接中楼主所说的九宫格就是三阶幻方,又看到了namejm的精彩代码~~不过此题要求是n阶幻方(暂定为奇数阶),下面11楼 pengfei所上传的附件sigil.exe符合此题题意。虽然没提供代码,但是提供了算法。大家尝试着看谁能写出代码?

TOP

返回列表