暑假闲来无聊,于是想到将本科四年的一些作业和项目稍加整理,加以总结写到博客中,以便日后查阅,也可以和大家互相学习进步。
第一篇就是大一刚学c++时候的作业-八皇后问题,然后深入考虑n皇后问题。
当时的代码如下:
#include <iostream>
#include <cmath>
#include <time.h>
#include <algorithm>
#include <vector>
using namespace std;
int result[1000]; //利用数组储存问题的解
vector<int> resultVec;
bool QueenRecursive(const int n,const int t) //利用递归求解
{
if(t==n)
{
cout<<"解决方案:"<<endl;
for(int l=0;l<n;l++)
{
cout<<result[l]<<" ";
}
return true;
}
else
{
for(int j=0;j<n;j++)
{
result[t]=j;
bool flag = true;
for(int k=0;k<t;k++)
{
if((abs(result[t]-result[k])==t-k)||(result[t]==result[k]))
{
flag = false;
}
}
if(flag == true) //如果符合就继续递归
{
if(QueenRecursive(n,t+1) == true)
{
return true;
}
}
}
}
}
bool PassCheck()
{
bool flag = true;
for(int i=0;i!=resultVec.size();i++)
{
for(int j=0;j!=i;j++)
{
if((abs(resultVec[i]-resultVec[j]) == i-j) || (resultVec[i] == resultVec[j]))
{
flag = false;
break;
}
}
if(!flag)
{
break;
}
}
return flag;
}
void QueenPermutation(int n)
{
resultVec.resize(n);
for(int i=0;i!=n;i++)
{
resultVec[i]=i;
}
while(next_permutation(resultVec.begin(),resultVec.end()))
{
if(PassCheck())
{
for(int i=0;i!=resultVec.size();i++)
{
cout<<resultVec[i]<<" ";
}
break;
}
}
}
int main() //主函数 想求解的皇后个数为n
{
int n;
cout<<"输入皇后的个数(必须为正整数):"<<endl;
cin>>n;
clock_t beginTime = 0;
clock_t endTime = 0;
beginTime = clock();
QueenRecursive(n,0);
endTime = clock();
cout<<"回溯法用时:"<<endTime-beginTime<<"ms"<<endl;
beginTime = clock();
QueenPermutation(n);
endTime = clock();
cout<<"全排列法用时:"<<endTime-beginTime<<"ms"<<endl;
return 0;
}
主要采用了两种方法求解,一种是递归,一种是全排列法。全排列法非常直观,但是效率很慢。递归的效率要比全排列法高很多,在n越大时越明显。
递归的基本思想:result数组存储的是每一列上皇后所在的位置(0~n-1),在确定了第j列的皇后位置之后,第j+1列的位置就需要根据前j列来确定,依此类推,直到所有n列的位置都确定之后就是一种解决方案,这里的递归好比n个for循环。
全排列思想:就是对每一个全排列进行检查,如果符合条件就输出。
对于n皇后问题,如果只需要找出一组解,有一种最快速的方法就就是:
一、当n%6 != 2 或 n%6 != 3时,有一个解为:
2,4,6,8,...,n,1,3,5,7,...,n-1 (n为偶数)
2,4,6,8,...,n-1,1,3,5,7,...,n (n为奇数)
二、当n%6 == 2 或 n%6 == 3时,
(当n为偶数,k=n/2;当n为奇数,k=(n-1)/2)
k,k+2,k+4,...,n,1,2,4,...,k-2,k+3,k+5,...,n-1,1,3,5,...,k+1 (k为偶数,n为偶数)
k,k+2,k+4,...,n-1,2,4,...,k-2,k+3,k+5,...,n-2,1,3,5,...,k+1,n (k为偶数,n为奇数)
k,k+2,k+4,...,n-1,1,3,5,...,k-2,k+3,...,n,2,4,...,k+1 (k为奇数,n为偶数)
k,k+2,k+4,...,n-2,1,3,5,...,k-2,k+3,...,n-1,2,4,...,k+1,n (k为奇数,n为奇数)