The BackTracking algorithm for n queen problem

The article is about the design of algorithm for n queen problem. The intention of this article is from an excise of an algorithm book: <<Introduction to the design and analysis of algorithms>>. This backtracking algorithm is interesting, so I decide to record the process of implementation. First, I use a double dimension array to simulate the chess board. But quickly I have found this form of representation is not so convenient especially in the check function that is used to checking whether or not current solution is promising. Because the check function is worked with the index of array, the value of array is trivial. i.e. a[0][0] = 1 represent (0,0) position of chess board has a chess and the next chess can't be position (0,1) and (0,0).  The pair (0,0) already indicate position (0,0) has a chess, it is unnecessary to assigning a value 1 to pair (0,0) to denoting (0,0) has chess. So I have changed a representation of chess position by vector<pair<int,int> >. Apparently, pair<int, int> stands for (x,y). Notice that a solution of n queen require each row is different. That is, for a solution of n queen, each of pair_instance.first must distinct. This simplifies the representation further. It just needs a vector<int> to represent a chess board. So the solution of n queen problem can be viewed as a permutation of natural number from 0 to n-1. Apparently, the brute-force algorithm has efficiency Ω(n!).

For the part of check function, I have observed the characteristic of permutation that is confirmed with n queen problem. The rule is defined as follow:

If the number of position p in permutation is i, then the vaule of position q(denoted by j) can't be q-p+i or p-q+i.(q(p,n-1] );

REVIST: (0,0)(1,2)(2,4)(3,3)(4,1) is a illegal solution which can be viewed as 0,2,4,3,1simply. 4(i) in position 2(p), 3(q's vaule: j) in position 3(q) ------ q-p+i = 5(no violation); p-q+i = 3(violation). (starting from zero))

It requires a two nested for loop to attaining. In addition, if there exist a method to constructing a NFA to recognize the permutation, the n queen problem algorithm will have Θ(n) efficiency class. But it seems impossible to do that because the FA needs counting and no way to abstract states.

The codes:

#include <iostream>

#include <vector>

#include <algorithm>

#include <utility>

#include <functional>

#include <ctime>

using namespace std;

 

template<class T>

struct output_functor : public unary_function<T,void>

{

     void operator()(const T& p)const

     {

         cout<<"("<<p.first<<","<<p.second<<")"<<"  ";

     }

};

 

class chess_board

{

     vector<pair<int, int> > position;

     vector<int> array;

     vector<int> duplicate_array;

     public:

     int n;

     int cur_i;

     int number_solution;

     chess_board(int dim):n(dim),cur_i(0),number_solution(0)

     {

         position.reserve(n);

         array.resize(n,-30000);//if using -1 to denoting no chess, it will contradict with the diagonal test. i.e. move{0,0}.the content of array is {0,-1,-1,-1}.the diagonal test will return false. So I use -30000 to express the meaning, but it is still imperfect. it is requiring a number to denoting impossible number or infinity simply

         duplicate_array.resize(n,0);

         for(int i=0; i<n; i++)

         {

              position.push_back(make_pair(i,-1));

         }

     }

     void move(int j)

     {

         position[cur_i].second=j;

         array[cur_i]=j;

         if(duplicate_array[j]==0)

              duplicate_array[j]=1;

         else

              duplicate_array[j]=2;

     }

     void un_move(int j)

     {

         position[cur_i].second=-1;

         array[cur_i]=-30000;

         if(duplicate_array[j]==1)

              duplicate_array[j]=0;

         else

              duplicate_array[j]=1;

     }

     bool check()

     {

         vector<int>::iterator i = std::find(duplicate_array.begin(),duplicate_array.end(),2);

         if(i != duplicate_array.end())

              return false;

         if(check_permutation(array) == false)

              return false;

         return true;

     }

     void write()

     {

         number_solution++;

         for_each(position.begin(), position.end(), output_functor<pair<int,int> >());

         cout<<endl;

     }

     private:

     bool check_permutation(const vector<int>& p)

     {

         for(int i=0; i<n; i++)

         {

              for(int j=i+1,d=1; j<n; j++,d++)

              {

                   if(p[i]+d == p[j] || p[i]-d == p[j])

                       return false;

              }

         }

         return true;

     }

};

void BackTracking(chess_board& c)

{

     if(c.check() == false)

     {

         c.cur_i -= 1;

         return;

     }

     else

     {

         if(c.cur_i == c.n)// this equality comparison is some tricky, note that following a move(), and assuming a solution has been generated, then cur_i will increase by 1.so in the recurrence of BackTracking cur_i will exceed the meaning of a position so that it will compare with n rather than n-1

         {

              c.write();

              c.cur_i-=1; //this sentence is cope with the situation in which BackTracking terminated after a solution has been found

              return;

         }

         else

         {

              for(int j=0; j<c.n; j++)

              {

                   c.move(j);

                   c.cur_i += 1;

                   BackTracking(c);

                   c.un_move(j);

              }

              c.cur_i -= 1; //this sentence is cope with the situation in which BackTracking terminated after for loop over

         }

     }

}

int main()

{

     int n;

     cout<<"input the number of queen: ";

     cin>>n;

     chess_board c(n);

     clock_t t1 = clock();

     BackTracking(c);

     cout<<"The number of solutions is: "<<c.number_solution<<endl;

     clock_t t2 = clock(); 

      cout<<"Times took:"<<double(t2-t1)/CLOCKS_PER_SEC; 

        system("pause"); 

         return 0;

}

 

 

 

Note that this is just a “pure” BackTracking algorithm and it has not considered the optimization. I will optimize it later.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Practice 1 Date: Monday, March 18th, 2013 We highly encourage being environment friendly and trying all problems on your own. Implement exercise 2.3-7. Implement priority queue. Implement Quicksort and answer the following questions. (1) How many comparisons will Quicksort do on a list of n elements that all have the same value? (2) What are the maximum and minimum number of comparisons will Quicksort do on a list of n elements, give an instance for maximum and minimum case respectively. Give a divide and conquer algorithm for the following problem: you are given two sorted lists of size m and n, and are allowed unit time access to the ith element of each list. Give an O(lg m + lgn) time algorithm for computing the kth largest element in the union of the two lists. (For simplicity, you can assume that the elements of the two lists are distinct). Practice 2 Date: Monday, April 1st, 2013 We highly encourage being environment friendly and trying all problems on your own. Matrix-chain product. The following are some instances. Longest Common Subsequence (LCS). The following are some instances. X: xzyzzyx Y: zxyyzxz X:MAEEEVAKLEKHLMLLRQEYVKLQKKLAETEKRCALLAAQANKESSSESFISRLLAIVAD Y:MAEEEVAKLEKHLMLLRQEYVKLQKKLAETEKRCTLLAAQANKENSNESFISRLLAIVAG Longest Common Substring. The following are some instances. X: xzyzzyx Y: zxyyzxz X:MAEEEVAKLEKHLMLLRQEYVKLQKKLAETEKRCALLAAQANKESSSESFISRLLAIVAD Y:MAEEEVAKLEKHLMLLRQEYVKLQKKLAETEKRCTLLAAQANKENSNESFISRLLAIVAG Max Sum. The following is an instance. (-2,11,-4,13,-5,-2) Shortest path in multistage graphs. Find the shortest path from 0 to 15 for the following graph.   A multistage graph is a graph (1) G=(V,E) with V partitioned into K >= 2 disjoint subsets such that if (a,b) is in E, then a is in Vi , and b is in Vi+1 for some subsets in the partition; and (2) | V1 | = | VK | = 1.     Practice 3 Date: Monday, April 15th, 2013 We highly encourage being environment friendly and trying all problems on your own. Knapsack Problem. There are 5 items that have a value and weight list below, the knapsack can contain at most 100 Lbs. Solve the problem both as fractional knapsack and 0/1 knapsack. A simple scheduling problem. We are given jobs j1, j2… jn, all with known running times t1, t2… tn, respectively. We have a single processor. What is the best way to schedule these jobs in order to minimize the average completion time. Assume that it is a nonpreemptive scheduling: once a job is started, it must run to completion. The following is an instance. (j1, j2, j3, j4) : (15,8,3,10) Single-source shortest paths. The following is the adjacency matrix, vertex A is the source.  A B C D E A -1 3 B 3 2 2 C D 1 5 E -3 All-pairs shortest paths. The adjacency matrix is as same as that of problem 3.(Use Floyd or Johnson’s algorithm)     Practice 4 Date: Monday, May 8th, 2013 We highly encourage being environment friendly and trying all problems on your own. 0/1 Knapsack Problem. There are 5 items that have a value and weight list below, the knapsack can contain at most 100 Lbs. Solve the problem using back-tracking algorithm and try to draw the tree generated. Solve the 8-Queen problem using back-tracking algorithm.    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值