(八皇后问题分析)回溯法两种控制流程

来源:百度文库 编辑:神马文学网 时间:2024/06/13 12:05:49
/****************************************/回溯法控制流程一

将栈置为空;
while(还没找到解)
{ //进入下一阶段;
    将此阶段的第一个选择压入栈中;
    while(栈顶的选择不可行)
    {
       while(栈顶的选择为最后一个选择)
       {
          弹栈; //回溯;
          if(栈为空)
              return 无解;
       }
       将栈顶修改为其下一个选择;
    }
}
return 有解;


例子八皇后:
check函数初步实现:
bool check(Gstack const& board)
{ //栈顶刚放置了一个新皇后,检查这个皇后是否安全;
    int row = board.size() - 1;
    for(int k = 1; --row >= 0; ++k)
       if( (board[row] == board.top() )
         || (board[row] == board.top() + k)
         || (board[row] == board.top() - k)
         )
             return false;
         return true;
}

八皇后问题初步解:
int const num_queens = 8;
int const zero = 0;
int const seven = num_queens - 1;
bool eight_queen()
{
    Gstack board(num_queens);
    while(board.size() < num_queens) {
         board.push(zero);
         for(; !check(board); ++board.top()) {
              while(board.top() >= seven){ //top为最后一个选择;
              board.pop();
              if(board.empty())
                  return false; //无解;
              }
         }
    }
    write_board(board); //输出解;
    return true;
}/******************************************************/
/*********************************************************/回溯法控制流程二:

将栈置为空;
while(还没找到解)
{ //进入下一阶段;
    x = 此阶段第一个选择;
    while(x不可行)
    {
        while( x为本阶段的最后选择)
        {
            if(栈为空)
               return 无解;
            x =栈顶元素;
            弹栈;//回溯;
        }
        x = x的下一个选择;
    }
    将x压栈;
}
return 有解;


八皇后例子:
改进的check函数:
int const num_queens = 8;
int const zero = 0;
int const seven = num_queens - 1;
//对角线条数;
int const fifteen = 2*num_queens - 1;
bool column_free[num_queens];
bool diag_free[fifteen]; //正对角线;
bool inv_diag_free[fifteen]; //反对角线;
//检查位置(i,j)是否安全;
bool check(int i, int j)
{
    return column_free[j] && diag_free[i + j]
    && inv_diag_free[seven + i - j];
}

设置和移除皇后:
void set_queen(int i, int j)
{ //在(i,j)上设置一个皇后;
     column_free[j] = inv_diag_free[seven + i - j]
                    = diag_free[i + j] = false;
}
void remove_queen(int i, int j)
{ //将(i,j)上的皇后移除;
    column_free[j] = inv_diag_free[seven + i - j]
                   = diag_free[i + j] = true;
}


改进后的八皇后问题解:

bool eight_queen2() {
    fill_n(column_free, num_queens, true);
    fill_n(diag_free, fifteen; true);
    fill_n(inv_diag_free, fifteen, true);
    Gstack board(num_queens);
    while(board.size() < num_queens) {
      for(int j = zero; !check(board.size(), j); ++j){
        while(j >= seven) {
            if(board.empty())
                return false; //无解;
            j = board.top();
            board.pop();
            remove_queen(board.size(), j);
        }
      }
      set_queen(board.size(), j);
      board.push(j);
    }
    write_board(board); //输出解;
return true; //有解;
}/******************************************************/