会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将 8 个皇后放在棋盘上(有8×8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即 a=b1b2...b8, 其中bi(1≤bi≤8)为相应摆法中第 i 行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。给出一个数n,要求输出第n个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。
输入包含多组数据。
每组数据包含一个正整数n(1≤n≤92)。
对应每一组输入,输出第n个皇后串。
1 92
15863724 84136275
/*递归求出符合要求的串,思路比较清晰*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
bool isOK(string queen) //判断一个串各皇后位置是否冲突
{
for (int i = 0; i < queen.size(); i++)
{
for (int j = i + 1; j < queen.size(); j++)
{
if (j - i == (queen[j] - '0') - (queen[i] - '0') || j - i == (queen[i] - '0') - (queen[j] - '0'))
return false;
}
}
return true;
}
void getQueen(string queen, int begin, vector<string>& queen_list) //求一个串排除皇后位置冲突后的全排列
{
if (begin == queen.size() - 1 && isOK(queen)) queen_list.push_back(queen);
for (int i = begin; i < queen.size(); i++)
{
if (i != begin && queen[i] == queen[begin]) continue;
swap(queen[begin], queen[i]);
getQueen(queen, begin + 1, queen_list);
swap(queen[begin], queen[i]);
}
}
int main()
{
vector<string> res;
string queen = "12345678";
getQueen(queen, 0, res);
sort(res.begin(), res.end());
int b;
while (cin >> b)
{
int sum = 0, len = res[b - 1].size() - 1;
for (int i = 0; i <= len; i++)
sum += (res[b - 1][len - i] - '0') * pow(10, i);
cout << sum << endl;
}
system("pause");
return 0;
}
import java.util.*;
public class Main{
static int n;
static int[] x;
static long sum;
static ArrayList<Integer> arrayList=new ArrayList<Integer>();
public static long nQueen(int nn){
n=nn;
x=new int[n+1];
sum=0;
backtrack();
return sum;
}
public static void backtrack(){
x[1]=0;
int k=1;
while(k>0){
x[k]+=1;
while((x[k]<=n) && !place(k))
x[k]+=1;
if(x[k]<=n){
if(k==n){
String str="";
for(int i=0;i<=n;i++){
str+=x[i];
}
int number=Integer.valueOf(str);
arrayList.add(number);
}
else{
k++;
x[k]=0;
}
}else
k--;
}
}
public static boolean place(int k){
for(int i=1;i<k;i++){
if((Math.abs(i-k)==Math.abs(x[i]-x[k]))||(x[i]==x[k]))
return false;
}
return true;
}
public static void main(String[] args){
int n=8;
nQueen(8);
Collections.sort(arrayList);
Scanner scanner=new Scanner(System.in);
while(scanner.hasNext()){
int index=scanner.nextInt();
System.out.println(arrayList.get(index-1));
}
}
} import java.util.*;
public class Main {
public static List<String> list = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[][] arr = new int[8][8];
eight_queen(arr, 0, "");
while (sc.hasNext()) {
int n = sc.nextInt();
System.out.println(list.get(n - 1));
}
}
public static void eight_queen(int[][] arr, int row, String s) {
if(row > 7) list.add(s);
for (int i = 0; i < 8; i ++) {
if(check(arr, row, i)) {
arr[row][i] = 1;
eight_queen(arr, row + 1, s + (i + 1));
arr[row][i] = 0; // 回溯
}
}
}
public static boolean check(int[][] arr, int row, int col) {
// 检查列
for (int i = 0; i < 8; i ++) {
if(arr[i][col] == 1) return false;
}
// 检查右上到左下斜线
for (int i = row - Math.min(row, 7 - col), j = col + Math.min(row, 7 - col); i < 8 && j >= 0; i ++, j --) {
if(arr[i][j] == 1) return false;
}
// 检查左上到右下斜线
for (int i = row - Math.min(row, col), j = col - Math.min(row, col); i < 8 && j < 8; i ++, j ++) {
if(arr[i][j] == 1) return false;
}
return true;
}
}
我把之前的n皇后拿过来改了改
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<functional>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <exception>
#include <iomanip>
#include <memory>
#include <sstream>
#define INF 1000000
using namespace std;
class Queens {
public:
typedef pair<double, double> Pair;
vector<vector<Pair>> res;
bool checkAttack(int x, int y, vector<Pair>& place)
{
if (place.empty()) return false;
for (auto& pr : place)
{
if (x == pr.first || y == pr.second || abs(x - pr.first) == abs(y - pr.second))
return true;
}
return false;
}
void DFS(int n, int level, vector<Pair>& place)
{
if (level >= n)
{
res.emplace_back(place);
return;
}
for (int i = 0; i < n; ++i)
{
if (!checkAttack(level, i, place))
{
place.emplace_back(level, i);
DFS(n, level + 1, place);
place.pop_back();
}
}
}
void nQueens(int n)
{
vector<Pair> place;
place.reserve(n);
DFS(n, 0, place);
}
};
int main(int argc, char** argv)
{
//freopen("in.txt", "r", stdin);
Queens s;
s.nQueens(8);
int n;
while (cin >> n && n > 0 && n <= 92)
{
for (auto& i : s.res[n - 1])
cout << i.second + 1;
cout << endl;
}
return 0;
}
#include<iostream>
#include <vector>
#include <map>
using namespace std;
vector<vector<int> > table;
vector<int> list(8);
map<int, int> mp;
void initMap()
{ // 将二进制的列信息转化为十进制的列号,建立此映射
int a = 1;
for (int i = 0; i < 8; ++i)
mp[a << (7 - i)] = i;
}
void eigheQueue(int row, int ld, int rd, int cnt)
{
int pos, p;
if (row != (1 << 8) - 1)
{
pos = ((1 << 8) - 1) & (~(row | ld | rd));
while (pos)
{
p = pos & (~pos + 1);
pos = pos - p;
list[cnt] = mp[p] + 1;
eigheQueue(row | p, (ld | p) << 1, (rd | p) >> 1, cnt + 1);
}
}
else table.insert(table.begin(), list);
}
int main()
{
initMap();
eigheQueue(0, 0, 0, 0);
int n;
while (cin >> n)
{
for (auto i : table[n - 1]) cout << i;
cout << endl;
}
return 0;
}
// write your code here cpp
#include
using namespace std;
vector> ans;
int c[9];
int vis[3][20];
void serach(int cur)
{
if(cur == 8)
{
vectortp;
for(int i = 0;i<8;i++)
tp.push_back(c[i]+1);
ans.push_back(tp);
}
for(int i = 0;i<8;i++)
{
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+8])
{
c[cur] = i;
vis[0][i] = vis[1][cur+i] = vis[2][cur-i+8] = 1;
serach(cur+1);
vis[0][i] = vis[1][cur+i] = vis[2][cur-i+8] = 0;
}
}
}
int main()
{
int n;
string temp;
while(scanf("%d",&n)!= EOF)
{
memset(vis,0,sizeof(vis));
memset(c,-1,sizeof(c));
serach(0);
for(auto it:ans[n-1])
{
cout<<it;
}
cout<<endl;
}
}这应该是比较精简的代码了。模板来自刘汝佳的算法入门第二版的424页,该算法模板的简单,思路也很简单,代码简单了之后,思路就会更加清晰。
python代码
import sys
MAX = 8
queen = [0] * MAX * MAX
valid = [0] * MAX
solutions = []
count = 1
def putQueen(row):
global count
for i in xrange(MAX):
if queen[row*MAX + i] == 0:
valid[row] = i + 1
mark = setMark(row, i)
if row == MAX - 1:
solutions.append(sumValue(valid))
else:
putQueen(row+1)
unSetMark(mark)
def setMark(row, col):
"""mark"""
mark = []
for i in xrange(MAX):
if queen[row*MAX + i] ==0:
queen[row*MAX + i] = 1
mark.append((row, i))
for i in xrange(row, MAX):
if queen[i*MAX + col] ==0:
queen[i*MAX + col] = 1
mark.append((i, col))
r, c = row, col
while r < MAX and c < MAX:
if queen[r*MAX + c] == 0:
queen[r*MAX + c] = 1
mark.append((r, c))
r += 1
c += 1
r, c = row, col
while r < MAX and c >= 0:
if queen[r*MAX + c] == 0:
queen[r*MAX + c] = 1
mark.append((r, c))
r += 1
c -= 1
return mark
def unSetMark(mark):
for row, col in mark:
queen[row*MAX + col] = 0
def sumValue(nums):
sum = 0
for num in nums:
sum = sum * 10 + num
return sum
putQueen(0)
solutions.sort()
num = sys.stdin.readline()
while num:
print solutions[int(num.strip())-1]
num = sys.stdin.readline()
思路:全排列--> 找出符合要求的--> 排序-->直接取出
#include
using namespace std;
bool compare(vector &a){ //确认本顺序是否符合要求
for(int i=0;i<a.size();i++){
for(int j=i+1;j<a.size();j++)
{
if((i-j)==a[i]-a[j] || (j-i)==a[i]-a[j])
return false;
}
}
return true;
}
void find_all(vector> &n,vector &a,int begin){ // 找到所有的可能排列
int tmp = a[begin];
if(begin==a.size()-1){
if(compare(a)){
//printVector(a);
//printf("\n");
n.push_back(a);
}
else{
//printVector(a);
//printf("\n");
}
}
else{
for(int i=begin;i<a.size();i++){
vector b(a); //保持在a上进行互相交换
b[begin] = b[i];
b[i] = tmp;
find_all(n,b,begin+1);
}
}
}
vector trans(vector> &N){ //将二维数组转换成一维数组,方便后面排序
vector R;
for(int i=0;i<N.size();i++){
int sum=0;
//printVector(N[i]);
for(int j=0;j<N[0].size();j++){
sum+=N[i][j]*(int)pow(10.0,1.0*(N[0].size()-j-1));
//printf("sum = %d , ",sum);
}
//printf(" %d\n",sum);
R.push_back(sum);
}
return R;
}
int main(){
// 初始a[] = {1,2,3,4,5,6,7,8}
int a[8]={1,2,3,4,5,6,7,8};
vector A(&a[0],&a[8]);
vector> N;
find_all(N,A,0);
//printf("%ld\n",N.size());
vector R;
R = trans(N);
sort(R.begin(), R.end(),less());//升
//printf("%d",R[9]);
int num;
while(scanf("%d",&num)!=EOF){
printf("%d\n",R[num-1]);
}
/*scanf("%d",&n);
int *num= new int[n];
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
for(int i=0;i<n;i++)
printf("%d\n",R[num[i]-1]);
*/
return 0;
}
import java.util.*;
public class Main {
public static int[][] visited = new int[3][15];
public static int curCount=0;
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
help(0,n,new String());// 回溯求子串
}
}
// 回溯法求子串,因为是有序的,所以直接打印出第n个子串
public static int help(int curRow,int n,String sb) {
if (curRow == 8) {
if(++curCount==n){
System.out.println(sb);
curCount=0;
return 0;
}
return 1;
}
int reslut=1;
for (int curCol = 0; curCol < 8; curCol++) {
if (visited[0][curCol] == 0 && visited[1][curRow - curCol + 7] == 0
&& visited[2][curRow + curCol] == 0) {
visited[0][curCol] = 1;
visited[1][curRow - curCol + 7] = 1;
visited[2][curRow + curCol] = 1;
reslut=help(curRow + 1,n,sb + (curCol + 1));
visited[0][curCol] = 0;
visited[1][curRow - curCol + 7] = 0;
visited[2][curRow + curCol] = 0;
if(reslut==0)
break;
}
}
return reslut;
}
}