八皇后问题
Feynman和朋友们下国际象棋,(棋盘为8x8)。下到兴致之处,Feynman突发奇想:如果将64个格子分别赋值,并拿出八个皇后棋子(国际象棋中的皇后可以将同一行、同一列和同一对角线上的对方棋子吃掉。)
Feynman想怎么摆放这八个皇后的位置才能让她们不互相攻击的同时八个皇后所在格子的和最大。
输入格式
每个棋盘有64个数字,分成8行8列输入,就如样例所示,分别表示格子的值。棋盘上每一个数字均小于100。
输出格式
输出一个最大的总和
样例输入
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
样例输出
260
思路
利用递归的思想(DFS),搜索每行(因为满足皇后不冲突,一行只能摆放一个皇后)
设置标记数组,分别标记列,主对角线,次对角线。每次递归时(扫描行),枚举每列的情况,如果列没有标记,利用行列坐标计算出所在的主对角线和次对角线,判断两条对角线上有无标记,若行列对角线都无标记就将一个皇后放置在该坐标上,如果后续递归完不成任务(八皇后冲突了),递归退到前步,sum减坐标对应值,去除标记(dfs常用做法)。如果满足情况,在sum中遴选max即可。
如图红色对角线序号可由坐标表达式:7-l+i求得 黑色对角线序号可由坐标表达式l+i求得
代码示例
#include<iostream>
using namespace std;
int map[10][10];
int lie[8];//标记列
//直接标记共30条对角线,就不用一个个点进行x,y关系的比较了
int dui1[15];//标记从对角线
int dui2[15];//标记主对角线
int n=8;
int sum=0;
int max_x=-0xfffff;
void dfs(int l)//对行进行dfs
{
if(l==8){
//cout<<sum<<"..."<<endl;
if(max_x<sum) max_x=sum;
return ;
}
for(int i=0;i<8;++i){
if(lie[i]==0&&dui1[7-l+i]==0&&dui2[l+i]==0){
sum+=map[l][i];
lie[i]=1;
dui1[7-l+i]=1;
dui2[l+i]=1;
dfs(l+1);
sum-=map[l][i];
lie[i]=0;
dui1[7-l+i]=0;
dui2[l+i]=0;
}
}
}
int main()
{
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
cin>>map[i][j];
}
}
dfs(0);
cout<<max_x<<endl;
return 0;
}