zoukankan      html  css  js  c++  java
  • 八皇后回溯计算法研究

    仔细看了下百度中的回溯法介绍,这是一种非常有用的算法,大概有两种模式,一种是遍历,一种是递归。

    我把这两种方法都列出来了,按网上的说法,递归效率要比遍历快很多,我这里测试是一样的,可能是网络上那些遍历法根本没优化好吧,

    多遍历了很多东西。

    网上并没有Delphi的原代码,我综合了各种算法,将N阶皇后的算法一并写出来了。以下是原代码,希望有意研究的朋友跟我留言:

    //工程文件:Queen8.dpr,以下代码在Delphi2010下编译通过。

    program Queen8;

    uses
      Forms,
      uQueen8 in 'uQueen8.pas' {fmQueen8};

    {$R *.res}

    begin
      Application.Initialize;
      Application.MainFormOnTaskbar := True;
      Application.CreateForm(TfmQueen8, fmQueen8);
      Application.Run;
    end.

    //窗体单元文件:uQueen8.pas

    unit uQueen8;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics,
      Controls, Forms, Dialogs, StdCtrls, Buttons,
      Spin, ExtCtrls, StrUtils,DateUtils;

    type
      TfmQueen8 = class(TForm)
        spn1: TSpinEdit;
        btnRecurrence: TBitBtn;
        mem1: TMemo;
        lbl1: TLabel;
        pnl1: TPanel;
        mem2: TMemo;
        btnGoThrough: TBitBtn;
        procedure btnRecurrenceClick(Sender: TObject);
        procedure btnGoThroughClick(Sender: TObject);
      private
        { Private declarations }
        Queen : array of Integer;
        StyleCount : Integer;
      public
        { Public declarations }
        procedure OutputStyle(AStrs : TStrings; AQueen : array of Integer);
      end;

    var
      fmQueen8: TfmQueen8;

    implementation

    {$R *.dfm}

    {输入和判断应该是两个公用方法,传统遍历和递归都是一样的。}
    procedure OutputData(AStrs : TStrings; AQueen : array of Integer; AStyleCount : Integer);
    var
      ASize : Integer; //数组长度
      ALine : string;  //记录一行字串
      i , j : Integer; //循环变量
    begin
      //AStrs.Clear;
      AStrs.Append('==StyleNo:'+inttostr(AStyleCount)+'==');
      ASize := High(AQueen)-Low(AQueen)+1;
      for i := Low(AQueen) to High(AQueen) do
      begin
        ALine := DupeString('☆',AQueen[i]) + '★'+ DupeString('☆',ASize-Aqueen[i]-1);
        AStrs.Append(ALine);
      end;
      AStrs.Append('==========');
    end;

    //判断新皇后位置是否成立,其判断的位置坐标X,Y
    function JudgeQueen(AQueen : array of Integer; APositionY, APositionX : Integer) : Boolean;
    var
      x , y : Integer;    // x,y对应其临时比较值的横,纵坐标
    begin
      Result := False;
      if APositionY>High(AQueen) then
        Exit;
      for y := 0 to APositionY-1 do
      begin
        x  := AQueen[y];
        if x=APositionX then              //比较竖直线
          Exit;
        if x+y=APositionX+APositionY then //比较左上到右下的斜线
          Exit;
        if x-y=APositionX-APositionY then //比较右上到左下的斜线
          Exit;
      end;
      Result := True;
    end;

    { TfmQueen8 }

    procedure TfmQueen8.btnRecurrenceClick(Sender: TObject);
    var
      i,StyleCount : Integer;
      Queen : array of Integer; //皇后数据
      QueenSize : Integer; //皇后数目
      TimeTemp : TDateTime;
      //进行皇后的递归计算
      procedure Calc(AQueen : array of Integer; AIndex : Integer; var AStyleCount : Integer);   //AIndex意义是,已成功检查完几阶
      var
        i : Integer;
      begin
        for i := Low(AQueen) to High(AQueen) do
        begin
          if JudgeQueen(AQueen,AIndex,i) then
          begin
            AQueen[AIndex] := i;
            if AIndex=High(AQueen)-Low(AQueen) then
            begin
              Inc(AStyleCount);
              OutputData(mem1.Lines,AQueen,AStyleCount);
              //AQueen[AIndex] :=0;
              //Sleep(1000);
              Break;
            end
            else
              Calc(AQueen,AIndex+1,StyleCount);
            //AQueen[AIndex] :=i;
          end;

        end;
      end;
    begin
      StyleCount :=0;
      QueenSize :=spn1.Value;
      SetLength(Queen,QueenSize);
      for i := Low(Queen) to High(Queen) do
      begin
        Queen[i] := 0;
      end;
      TimeTemp := Now;
      Calc(Queen,0,StyleCount);
      mem1.Lines.Append(#13+'总共耗时'+inttostr(MilliSecondsBetween(TimeTemp,Now))+'毫秒');
    end;

    procedure TfmQueen8.btnGoThroughClick(Sender: TObject);
    var
      i,StyleCount : Integer;
      Queen : array of Integer; //皇后数据
      QueenSize : Integer; //皇后数目
      TimeTemp : TDateTime;

      //进行皇后的遍历计算
      procedure Calc(AQueen : array of Integer; var AStyleCount : Integer);
      var
        i, Index : Integer;               //Index意义是,当前变动的阶数
      begin
        Index := 0;                       //从第一个数开始检查起,这个跟递归初始化的参数一样。
        while Index>=0 do                 //循环比较特殊,这里不能用For循环,因为循环的控制很复杂。
        begin
          Inc(AQueen[Index]);             //先赋值,再对已赋值的数据进行判断。
          while (AQueen[Index]<=High(AQueen)-Low(AQueen)) and not (JudgeQueen(AQueen,Index,AQueen[Index])) do
            Inc(AQueen[Index]);           //当前数据检查不通过时,直接转到当前行的下一列。
          if (AQueen[Index]<=High(AQueen)-Low(AQueen)) and (Index=High(AQueen)-Low(AQueen)) then
          begin                           //当数据检查通过,而Index满阶的时候,就直接输出。
            Inc(AStyleCount);
            OutputData(mem2.Lines,AQueen,AStyleCount);
          end
          else if (AQueen[Index]<=High(AQueen)-Low(AQueen)) and (Index<High(AQueen)-Low(AQueen))  then
          begin
            Inc(Index);                   //不满阶的时候,直接转下一行。
          end
          else                            //最后这种情况,其实是AQueen[Index]已经超出边界了,
          begin                           //也就是这行根本没有合适位置,那么就跳转上一行,并且让上一行列增加
            AQueen[Index]:=-1;
            Dec(Index);                   //这里只需要调整行,列调整在下次循环首句处理。
          end;
        end;
      end;
    begin
      StyleCount :=0;
      QueenSize :=spn1.Value;
      SetLength(Queen,QueenSize);
      for i := Low(Queen) to High(Queen) do
      begin
        Queen[i] := -1;
      end;
      TimeTemp := Now;
      Calc(Queen,StyleCount);
      mem2.Lines.Append(#13+'总共耗时'+inttostr(MilliSecondsBetween(TimeTemp,Now))+'毫秒');
    end;

    procedure TfmQueen8.OutputStyle(AStrs: TStrings; AQueen: array of Integer);
    var
      QSize : Integer;
      i,j : Integer;
      ALine : string;
    begin
      QSize := High(AQueen)-Low(AQueen);
      //未完成,这里想定义输出的各种符号风格来的。
    end;

    end.

    //窗体代码文件uQueen8.dfm

    object fmQueen8: TfmQueen8
      Left = 0
      Top = 0
      Caption = 'Queen8'
      ClientHeight = 388
      ClientWidth = 528
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object lbl1: TLabel
        Left = 8
        Top = 8
        Width = 48
        Height = 13
        Caption = #30343#21518#25968#30446
      end
      object spn1: TSpinEdit
        Left = 62
        Top = 6
        Width = 121
        Height = 22
        MaxValue = 0
        MinValue = 0
        TabOrder = 0
        Value = 8
      end
      object btnRecurrence: TBitBtn
        Left = 32
        Top = 44
        Width = 137
        Height = 25
        Caption = #39640#25928#36882#24402#22238#26388#27861#35745#31639
        DoubleBuffered = True
        ParentDoubleBuffered = False
        TabOrder = 1
        OnClick = btnRecurrenceClick
      end
      object pnl1: TPanel
        Left = 0
        Top = 88
        Width = 528
        Height = 300
        Align = alBottom
        TabOrder = 2
        object mem1: TMemo
          Left = 1
          Top = 1
          Width = 255
          Height = 298
          Align = alClient
          TabOrder = 0
        end
        object mem2: TMemo
          Left = 256
          Top = 1
          Width = 271
          Height = 298
          Align = alRight
          TabOrder = 1
        end
      end
      object btnGoThrough: TBitBtn
        Left = 280
        Top = 44
        Width = 169
        Height = 25
        Caption = #20256#32479#36941#21382#22238#26388#27861#35745#31639
        DoubleBuffered = True
        ParentDoubleBuffered = False
        TabOrder = 3
        OnClick = btnGoThroughClick
      end
    end

  • 相关阅读:
    常用的STL
    CString,string,char数组的转换
    linux知识
    十一种通用滤波算法(转)
    修复被勒索病毒cl0p损坏的svn代码
    android shell 转发代理shell示例
    3proxy配置
    windbg调试写dmp,随机名字
    nexus6p刷机注意
    mysql语句学习
  • 原文地址:https://www.cnblogs.com/Murphieston/p/6270420.html
Copyright © 2011-2022 走看看