引入:为了点击量丧心病狂地添加了蓝桥杯三个字,虽然并没有什么用
1. 八皇后问题
以国际象棋为背景:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。
使用回溯和递归的方法进行的求解
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <cmath>
using namespace std;
int a[10][10];
// 摆在每行的哪一列
int thehang[10];
// 哪一列是否已有了
int ishas[10];
// 有多少组
int flag = 0;
void put(int hang, int lei)
{
if (thehang[8] != 0)
{
for (int i = 1; i <= 8; i++)
{
printf_s("%d",thehang[i]);
}
cout << endl;
flag++;
return;
}
if (hang > 8 || lei > 8)
return;
// 第一行
if (hang == 1)
{
a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
// 从下一行第一列开始找
put(hang + 1, 1);
// 回溯,即返回到原来的样子
a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
}
// 非第一行
else {
// 做下一行处理
int temp;
for (temp = 1; temp < hang; temp++)
{
// 是否同列有,对角线有(每行比)
if (hang - temp == abs(thehang[temp] - lei) || thehang[temp] == lei)
{
put(hang, lei + 1);
return;
}
}
if(temp==hang)
{
a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
put(hang + 1, 1);
a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
}
}
if (lei < 8)
put(hang, lei + 1);
}
int main()
{
memset(a, 0, sizeof(a));
memset(ishas, 0, sizeof(ishas));
put(1, 1);
printf_s("%d", flag);
}
2. n皇后问题
棋盘的大小变为n×n,而皇后个数也变成n。(0<n<=10)
递归函数里增加一个参数表示n,用n来代替8,会了八皇后直接改参数就可以了
真是个小天才
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <cmath>
using namespace std;
int a[10][10];
// 摆在每行的哪一列
int thehang[10];
// 哪一列是否已有了
int ishas[10];
// 有多少组
int flag = 0;
void put(int hang, int lei, int size)
{
if (thehang[size] != 0)
{
for (int i = 1; i <= size; i++)
{
printf_s("%d",thehang[i]);
}
cout << endl;
flag++;
return;
}
if (hang > size || lei > size)
return;
// 第一行
if (hang == 1)
{
a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
// 从下一行第一列开始找
put(hang + 1, 1, size);
// 回溯,即返回到原来的样子
a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
}
// 非第一行
else {
// 做下一行处理
int temp;
for (temp = 1; temp < hang; temp++)
{
// 是否同列有,对角线有(每行比)
if (hang - temp == abs(thehang[temp] - lei) || thehang[temp] == lei)
{
put(hang, lei + 1, size);
return;
}
}
if(temp==hang)
{
a[hang][lei] = 1; ishas[lei] = 1; thehang[hang] = lei;
put(hang + 1, 1, size);
a[hang][lei] = 0; ishas[lei] = 0; thehang[hang] = 0;
}
}
if (lei < size)
put(hang, lei + 1, size);
}
int main()
{
int n;
cin >> n;
memset(a, 0, sizeof(a));
memset(ishas, 0, sizeof(ishas));
put(1, 1, n);
printf_s("%d", flag);
}
3. 2n皇后问题
问题来自于蓝桥杯
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
方法基本一致,细节以后再来解释
毕竟调试地要吐了
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <cmath>
using namespace std;
int a[10][10];
// 白摆在每行的哪一列
int thehang[10];
// 白哪一列是否已有了
int ishas[10];
// 黑摆在每行的哪一列
int black_thehang[10];
// 黑哪一列是否已有了
int black_ishas[10];
// 有多少组
int flag = 0;
// 放黑皇后(0:不能放; 1:可以放; 2:放过白的了; 3:放过黑的了)
void put_black(int hang, int lei, int size)
{
// 达成一次2n问题
if (black_thehang[size] != 0)
{
flag++;
return;
}
if (hang > size || lei > size)
return;
// 第一行
if (hang == 1)
{
if (a[hang][lei] == 1)
{
a[hang][lei] = 3; black_ishas[lei] = 1; black_thehang[hang] = lei;
// 从下一行第一列开始找
put_black(hang + 1, 1, size);
// 回溯,即返回到原来的样子
a[hang][lei] = 1; black_ishas[lei] = 0; black_thehang[hang] = 0;
}
}
// 非第一行
else {
// 做下一行处理
int temp;
for (temp = 1; temp < hang; temp++)
{
// 是否同列有,对角线有(每行比)
if (hang - temp == abs(black_thehang[temp] - lei) || black_thehang[temp] == lei || a[hang][lei] != 1)
{
put_black(hang, lei + 1, size);
return;
}
}
if (temp == hang)
{
a[hang][lei] = 3; black_ishas[lei] = 1; black_thehang[hang] = lei;
put_black(hang + 1, 1, size);
a[hang][lei] = 1; black_ishas[lei] = 0; black_thehang[hang] = 0;
}
}
if (lei < size)
put_black(hang, lei + 1, size);
}
// 放白皇后(0:不能放; 1:可以放; 2:放过白的了)
void put(int hang, int lei, int size)
{
if (thehang[size] != 0)
{
// 白的已经放好了
put_black(1, 1, size);
return;
}
if (hang > size || lei > size)
return;
// 第一行
if (hang == 1)
{
if (a[hang][lei] == 1)
{
a[hang][lei] = 2; ishas[lei] = 1; thehang[hang] = lei;
// 从下一行第一列开始找
put(hang + 1, 1, size);
// 回溯,即返回到原来的样子
a[hang][lei] = 1; ishas[lei] = 0; thehang[hang] = 0;
}
}
// 非第一行
else {
// 做下一行处理
int temp;
for (temp = 1; temp < hang; temp++)
{
// 是否同列有,对角线有(每行比)
if (hang - temp == abs(thehang[temp] - lei) || thehang[temp] == lei || a[hang][lei] == 0)
{
put(hang, lei + 1, size);
return;
}
}
if(temp==hang)
{
a[hang][lei] = 2; ishas[lei] = 1; thehang[hang] = lei;
put(hang + 1, 1, size);
a[hang][lei] = 1; ishas[lei] = 0; thehang[hang] = 0;
}
}
if (lei < size)
put(hang, lei + 1, size);
}
int main()
{
int n;
cin >> n;
memset(a, 0, sizeof(a));
memset(ishas, 0, sizeof(ishas));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
scanf("%d", &a[i][j]);
}
put(1, 1, n);
printf("%d", flag);
}