n个皇后,每两个皇后之间不能在同一行,同一列,同一对角线上
(i,Xi),(j,Xj)不在同一主对角线上为Xi-i!=Xj-j,即Xi-Xj!=i-j;
不在同一负对角线上为Xi+i!=Xj+j,即Xi-Xj!=j-i;
合并为abs(Xi-Xj)!=(i-j)
/*
n个皇后,每两个皇后之间不能在同一行,同一列,同一对角线上
(i,Xi),(j,Xj)不在同一主对角线上为Xi-i!=Xj-j,即Xi-Xj!=i-j;
不在同一负对角线上为Xi+i!=Xj+j,即Xi-Xj!=j-i;
合并为abs(Xi-Xj)!=(i-j)
*/
//第一种解法
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=200;
int p[maxn],ans=0;
bool hashTable[maxn]={0};
void fullper(int index,int n);
int temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;
int main()
{
int n;
printf("输入一个正整数:\n");
scanf("%d",&n);
fullper(1,n);
cout << ans << endl;
cout << "temp1: " << temp1 << endl;
cout << "temp2: " << temp2 << endl;
cout << "temp3: " << temp3 << endl;
cout << "temp4: " << temp4 << endl;
cout << "temp5: " << temp5 << endl;
return 0;
}
void fullper(int index,int n)
{
if(index==n+1)
{
++ans;
cout << ans << "th:\n";
for(int i=1;i<=n;++i)
{
cout << p[i];
if(i<n)
cout << ' ';
else
cout << endl;
}
}
else
{
for(int i=1;i<=n;++i)
{
++temp1;
if(hashTable[i]==0)
{
++temp2;
bool flag=true;
for(int j=1;j<index;++j)
{
++temp3;
if(abs(i-p[j])==abs(index-j))
{
++temp4;
flag=false;
break;
}
}
if(flag)
{
++temp5;
p[index]=i;
hashTable[i]=1;
fullper(index+1,n);
hashTable[i]=0; //清理现场,将之前占用的位置给释放掉
}
}
}
}
}
第二种解法
(x,y)所在的主对角线上的方程为y=x+b,所以y-x=b;y-x的范围为[-n+1,n-1];
所在的负对角线上的方程为y=-x+b,所以y+x=b;y+x的范围为[2,2*n];
所以用i-j+n [1,2*n-1]对主对角线编号,用i+j [2,2*n]对负对角线编号。
/**
第二种解法
(x,y)所在的主对角线上的方程为y=x+b,所以y-x=b;y-x的范围为[-n+1,n-1];
所在的负对角线上的方程为y=-x+b,所以y+x=b;y+x的范围为[2,2*n];
所以用i-j+n [1,2*n-1]对主对角线编号,用i+j [2,2*n]对负对角线编号。
*/
/**
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=20;
int p[maxn],c[2*maxn]={0},d[2*maxn]={0};
bool hashTable[maxn]={0};
int n,ans=0;
void fullper(int index);
void output();
int temp_min=0,temp_max=0;
int main()
{
printf("输入一个正整数:\n");
scanf("%d",&n);
fullper(1);
cout << ans << endl;
cout << "temp_max: " << temp_max << endl;
cout << "temp_min: " << temp_min << endl;
return 0;
}
void fullper(int index)
{
for(int j=1;j<=n;++j)
{
++temp_max;
if(hashTable[j]==0&&c[index-j+n]==0&&d[index+j]==0)
{
++temp_min;
p[index]=j;
hashTable[j]=1;
c[index-j+n]=1;
d[index+j]=1;
if(index<n)
fullper(index+1);
else
output();
hashTable[j]=0; //以下三条语句都在清理现场
c[index-j+n]=0;
d[index+j]=0;
}
}
}
void output()
{
++ans;
cout << ans << "th:\n";
for(int i=1;i<=n;++i)
{
cout << p[i];
if(i<n)
cout << ' ';
else
cout << endl;
}
}
*/
第三种解法:
先给出解的全排列,每一次只交换两个数的值,直到满足条件,
此等算法又比一个一个的判断是否满足条件,要好上许多
(x,y)所在的主对角线上的方程为y=x+b,所以y-x=b;y-x的范围为[-n+1,n-1];
所在的负对角线上的方程为y=-x+b,所以y+x=b;y+x的范围为[2,2*n];
所以用i-j+n [1,2*n-1]对主对角线编号,用i+j [2,2*n]对负对角线编号。
/**
第三种解法:
先给出解的全排列,每一次只交换两个数的值,直到满足条件,
此等算法又比一个一个的判断是否满足条件,要好上许多
(x,y)所在的主对角线上的方程为y=x+b,所以y-x=b;y-x的范围为[-n+1,n-1];
所在的负对角线上的方程为y=-x+b,所以y+x=b;y+x的范围为[2,2*n];
所以用i-j+n [1,2*n-1]对主对角线编号,用i+j [2,2*n]对负对角线编号。
*/
/**
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=20;
int p[maxn],c[2*maxn]={0},d[2*maxn]={0};
bool hashTable[maxn]={0};
int n,ans=0;
void fullper(int index);
void output();
int temp_min=0,temp_max=0;
int main()
{
printf("输入一个正整数:\n");
scanf("%d",&n);
for(int i=1;i<=n;++i)
p[i]=i;
fullper(1);
cout << "total: " << ans << endl;
cout << "temp_max: " << temp_max << endl;
cout << "temp_min: " << temp_min << endl;
return 0;
}
void fullper(int index)
{
for(int j=index;j<=n;++j)
{
++temp_max;
swap(p[index],p[j]);
if(c[index-p[index]+n]==0&&d[index+p[index]]==0)
{
++temp_min;
c[index-p[index]+n]=1;
d[index+p[index]]=1;
if(index<n)
fullper(index+1);
else
output();
c[index-p[index]+n]=0; //以下三条语句都在清理现场
d[index+p[index]]=0;
}
swap(p[index],p[j]);
}
}
void output()
{
++ans;
cout << ans << "th:\n";
for(int i=1;i<=n;++i)
{
cout << p[i];
if(i<n)
cout << ' ';
else
cout << endl;
}
}
*/
皇后问题解法探讨:全排列与对角线策略

本文介绍了三种解决n皇后问题的方法,包括遍历全排列、利用对角线规则和交替交换皇后位置。通过实例代码展示了如何避免皇后在同一行、列或对角线上的冲突。
3296

被折叠的 条评论
为什么被折叠?



