版本1:
#include
using namespace std;
//a[i]存的是第i行的棋子放的列,我们的目标就是把1-n分配给a[1]-a[n],并且不能冲突
//vis[i][j]=1表示第i行第j列放了棋子,为0表示没放棋子
//vis1[i]=1表示第i列有棋子了,为0表示第i列没有棋子
int n, a[14], vis[14][14], vis1[14], ans;
//在x行y列放会不会产生冲突
bool ok(int x, int y)
{
//定义临时变量,不然x,y的值在一次while判断后就改变了,导致后面的判断失效
int tempx, tempy;
//判断同一行、同一列有没有冲突
//其实没有必要判断行(因为每行只安排一个数),没有必要判断列(vis1[i]表示第i列有没有数字)
/*
for(int i=1; i<=n; ++i){
if(vis[x][i]==1 || vis[i][y]==1){
return false;
}
}
*/
tempx=x;
tempy=y;
//判断左下角有没有冲突
while(tempx!=n && tempy!=1){
tempx++;
tempy--;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断右上角有没有冲突
while(tempx!=1 && tempy!=n){
tempx--;
tempy++;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断左上角有没有冲突
while(tempx!=1 && tempy!=1){
tempx--;
tempy--;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断右下角有没有冲突
while(tempx!=n && tempy!=n){
tempx++;
tempy++;
if(vis[tempx][tempy]==1){
return false;
}
}
return true;
}
//给第cnt行放棋子
void dfs(int cnt)
{
if(cnt==n+1){
ans++;
if(ans<=3){ //只输出前三种方案
for(int i=1; i<=n; ++i){
cout << a[i] << " ";
}
cout << endl;
}
return;
}
//看第cnt行要放在第几列,i遍历列
for(int i=1; i<=n; ++i){
//如果第cnt行第i列没有放棋子,并且第i列没有放棋子
//并且在cnt行i列放棋子不会产生冲突,才可以放
if(vis[cnt][i]==0 && vis1[i]==0 && ok(cnt, i)){
vis[cnt][i]=1;
vis1[i]=1;
a[cnt]=i;
dfs(cnt+1);
vis[cnt][i]=0;
vis1[i]=0;
}
}
}
int main()
{
cin >> n;
dfs(1);
cout << ans;
return 0;
}
#include
using namespace std;
//a[i]存的是第i行的棋子放的列,我们的目标就是把1-n分配给a[1]-a[n],并且不能冲突
//vis[i][j]=1表示第i行第j列放了棋子,为0表示没放棋子
//vis1[i]=1表示第i列有棋子了,为0表示第i列没有棋子
int n, a[14], vis[14][14], vis1[14], ans;
//在x行y列放会不会产生冲突
bool ok(int x, int y)
{
//定义临时变量,不然x,y的值在一次while判断后就改变了,导致后面的判断失效
int tempx, tempy;
//判断同一行、同一列有没有冲突
//其实没有必要判断行(因为每行只安排一个数),没有必要判断列(vis1[i]表示第i列有没有数字)
/*
for(int i=1; i<=n; ++i){
if(vis[x][i]==1 || vis[i][y]==1){
return false;
}
}
*/
tempx=x;
tempy=y;
//判断左下角有没有冲突
while(tempx!=n && tempy!=1){
tempx++;
tempy--;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断右上角有没有冲突
while(tempx!=1 && tempy!=n){
tempx--;
tempy++;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断左上角有没有冲突
while(tempx!=1 && tempy!=1){
tempx--;
tempy--;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断右下角有没有冲突
while(tempx!=n && tempy!=n){
tempx++;
tempy++;
if(vis[tempx][tempy]==1){
return false;
}
}
return true;
}
//给第cnt行放棋子
void dfs(int cnt)
{
//如果准备给第n+1行放棋子,说明前n行已经放好棋子了,说明本分支方案可行
if(cnt==n+1){
ans++;
cout << "第" << ans << "种方案:" << endl;
cout << " ";
for(int i=1; i<=n; ++i){
cout << " " << i << " ";
}
cout << endl;
for(int i=1; i<=n; ++i){
cout << " " << i << " ";
for(int j=1; j<=n; ++j){
if(j==a[i]){
cout << " * ";
}
else{
cout << " 0 ";
}
}
cout << endl;
}
cout << endl;
return;
}
//看第cnt行要放在第几列,i遍历列
for(int i=1; i<=n; ++i){
//如果第cnt行第i列没有放棋子,并且第i列没有放棋子
//并且在cnt行i列放棋子不会产生冲突,才可以放
if(vis[cnt][i]==0 && vis1[i]==0 && ok(cnt, i)){
vis[cnt][i]=1;
vis1[i]=1;
a[cnt]=i;
dfs(cnt+1);
vis[cnt][i]=0;
vis1[i]=0;
}
}
}
int main()
{
cin >> n;
//从第1行开始放棋子
dfs(1);
cout << n << "皇后问题,共有" << ans << "种方案";
return 0;
}
另外两种方法:
#include
using namespace std;
int n,ans,a[20];
int vis[20][20];
void dfs(int x){ //x表示第几行
if(x==n+1){
ans++;
if(ans<=3){
for(int i=1;i<=n;++i){
printf("%d ",a[i]);
}
printf("\n");
}
return;
}
for(int i=1;i<=n;++i){ //列举列数
if(vis[x][i]==0){
a[x]=i;
//右下角对角线打标记
for(int j=1;x+j<=n && i+j<=n;++j){
vis[x+j][i+j]++;
}
//对列打标记
for(int j=1;j<=n;++j){
vis[j][i]++;
}
//左上角对角线打标记
for(int j=1;x-j>=1 && i-j>=1;++j){
vis[x-j][i-j]++;
}
//右上角对角线打标记
for(int j=1;x-j>=1 && i+j<=n;++j){
vis[x-j][i+j]++;
}
//左对角线打标记
for(int j=1;x+j<=n && i-j>=1;++j){
vis[x+j][i-j]++;
}
dfs(x+1);
for(int j=1;x+j<=n && i+j<=n;++j){
vis[x+j][i+j]--;
}
for(int j=1;j<=n;++j){
vis[j][i]--;
}
for(int j=1;x-j>=1 && i-j>=1;++j){
vis[x-j][i-j]--;
}
for(int j=1;x-j>=1 && i+j<=n;++j){
vis[x-j][i+j]--;
}
for(int j=1;x+j<=n && i-j>=1;++j){
vis[x+j][i-j]--;
}
}
}
}
int main(){
scanf("%d",&n);
dfs(1);
printf("%d",ans);
return 0;
}
#include
using namespace std;
int n,l[15],temp;
bool vis[5][35];
bool check(int x,int y){
// for (int i=1;i<=num;++i){
// if (t[1][i]==x || t[2][i]==y || t[3][i]==a || t[4][i]==b){
// return 0;
// }
// }
if(vis[1][x] || vis[2][y] || vis[3][x-y+13] || vis[4][x+y]){
return 0;
}
return 1;
}
void ans(int x,int y){
if (x==n && check(x,y)){
l[x]=y;
if (temp<3){
for (int i=1;i<=n;++i){
printf("%d ",l[i]);
}
printf("\n");
}
++temp;
return;
}
if (check(x,y)){
l[x]=y;
// x
// t[1][num]=x;
//x行打标记
vis[1][x]=true;
// y
// t[2][num]=y;
//y列打标记
vis[2][y]=true;
// -
// t[3][num]=x-y+13;
//左上到右下对角线标记
vis[3][x-y+13]=true;
// +
// t[4][num]=x+y;
//右上到左下对角线标记
vis[4][x+y]=true;
for (int i=1;i<=n;++i){
ans(x+1,i);
}
vis[1][x]=false;
vis[2][y]=false;
vis[3][x-y+13]=false;
vis[4][x+y]=false;
}
return;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i){
ans(1,i);
}
printf("%d",temp);
return 0;
}
版本2:
#include
#include
using namespace std;
HANDLE outHandle=GetStdHandle(STD_OUTPUT_HANDLE);
//a[i]存的是第i行的棋子放的列,我们的目标就是把1-n分配给a[1]-a[n],并且不能冲突
//vis[i][j]=1表示第i行第j列放了棋子,为0表示没放棋子
//vis1[i]=1表示第i列有棋子了,为0表示第i列没有棋子
int n, a[14], vis[14][14], vis1[14], ans;
char asd=1;
//在x行y列放会不会产生冲突
bool ok(int x, int y)
{
//定义临时变量,不然x,y的值在一次while判断后就改变了,导致后面的判断失效
int tempx, tempy;
tempx=x;
tempy=y;
//判断左下角有没有冲突
while(tempx!=n && tempy!=1){
tempx++;
tempy--;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断右上角有没有冲突
while(tempx!=1 && tempy!=n){
tempx--;
tempy++;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断左上角有没有冲突
while(tempx!=1 && tempy!=1){
tempx--;
tempy--;
if(vis[tempx][tempy]==1){
return false;
}
}
tempx=x;
tempy=y;
//判断右下角有没有冲突
while(tempx!=n && tempy!=n){
tempx++;
tempy++;
if(vis[tempx][tempy]==1){
return false;
}
}
return true;
}
//给第cnt行放棋子
void dfs(int cnt)
{
//如果准备给第n+1行放棋子,说明前n行已经放好棋子了,说明本分支方案可行
if(cnt==n+1){
ans++;
//只输出一种方案
// if(ans>1) return;
cout << "第" << ans << "种方案:" << endl;
cout << " ";
for(int i=1; i<=n; ++i){
cout << " " << i << " ";
}
cout << endl << " -";
for(int i=1; i<=n; ++i){
cout << "----";
}
cout << endl;
for(int i=1; i<=n; ++i){
cout << " " << i << " |";
for(int j=1; j<=n; ++j){
if(j==a[i]){
SetConsoleTextAttribute(outHandle,0x0f);
cout << " " << asd;
SetConsoleTextAttribute(outHandle,0x07);
cout << " |";
}
else{
cout << " |";
}
}
cout << endl << " -";
for(int i=1; i<=n; ++i){
cout << "----";
}
cout << endl;
}
cout << endl;
return;
}
//看第cnt行要放在第几列,i遍历列
for(int i=1; i<=n; ++i){
//如果第cnt行第i列没有放棋子,并且第i列没有放棋子
//并且在cnt行i列放棋子不会产生冲突,才可以放
if(vis[cnt][i]==0 && vis1[i]==0 && ok(cnt, i)){
vis[cnt][i]=1;
vis1[i]=1;
a[cnt]=i;
dfs(cnt+1);
vis[cnt][i]=0;
vis1[i]=0;
}
}
}
int main()
{
cin >> n;
//从第1行开始放棋子
dfs(1);
cout << n << "皇后问题,共有" << ans << "种方案" << endl;
return 0;
}
另一种实现方法
#include
#include
using namespace std;
HANDLE outHandle=GetStdHandle(STD_OUTPUT_HANDLE);
//a[i]存的是第i行的棋子放的列,我们的目标就是把1-n分配给a[1]-a[n],并且不能冲突
//visl[i]=1表示第i列有棋子了,为0表示第i列没有棋子
//djx1[i]和djx2[i]表示对角线是否有棋子
int n, a[30], ans, visl[30], djx1[100], djx2[100];;
char asd=1;
void dfs(int cnt)
{
//如果准备给第n+1行放棋子,说明前n行已经放好棋子了,说明本分支方案可行
if(cnt==n+1){
ans++;
//只输出一种方案
if(ans>1) return;
cout << "第" << ans << "种方案:" << endl;
cout << " ";
for(int i=1; i<=n; ++i){
cout << " " << i << " ";
}
cout << endl << " -";
for(int i=1; i<=n; ++i){
cout << "----";
}
cout << endl;
for(int i=1; i<=n; ++i){
cout << " " << i << " |";
for(int j=1; j<=n; ++j){
if(j==a[i]){
SetConsoleTextAttribute(outHandle,0x0f);
cout << " " << asd;
SetConsoleTextAttribute(outHandle,0x07);
cout << " |";
}
else{
cout << " |";
}
}
cout << endl << " -";
for(int i=1; i<=n; ++i){
cout << "----";
}
cout << endl;
}
cout << endl;
return;
}
for(int i=1; i<=n; ++i){
if(!visl[i] && !djx1[cnt+i] && !djx2[n+cnt-i]){
visl[i]=djx1[cnt+i]=djx2[n+cnt-i]=true;
a[cnt]=i;
dfs(cnt+1);
visl[i]=djx1[cnt+i]=djx2[n+cnt-i]=false;
}
}
}
int main()
{
scanf("%d", &n);
dfs(1);
cout << n << "皇后问题,共有" << ans << "种方案" << endl;
return 0;
}