pta n皇后(回溯/递归)

对于皇后问题有的只要判断有多少种排列,有的要输出所有符合的图,本文我们将该两种问题代码及解题思路都给出来哦。

pta题目:

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 你的任务是,对于给定的N,求出有多少种合法的放置方法

输入格式:

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;

输出格式:

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量

输入样例:

在这里给出一组输入。例如:

1
8
5

输出样例:

在这里给出相应的输出。例如:

1
92
10

本题只用输出符合的个数即可,那么我们直接用一维数组对皇后位置进行存储 用递归进行处理,直接上代码(解题思路注释中给出)

#include 
using namespace std;
int su = 0,n;//记录有多少种
int arr[11];//该一维数组记录改行的皇后所在位置
bool useful(int i) {//判断是否有与第i行的皇后位置产生矛盾的其它皇后
	for (int j = 0; j < i; j++) 
		if (arr[i] == arr[j] || abs(arr[i] - arr[j]) == i - j) 
			return false;
	//abs(arr[i] - arr[j]) == i - j
	//斜率为+1/-1 即135度或45度
	return true;
}
void df(int i) {
	if (i == n) {
		su++;return;//满足则符合的加一
	}
	for (int j = 0; j < n; j++) {//i行的每一列进行判断
		arr[i] = j;
		if (useful(i)) //符合则继续往下一行查找
			df(i + 1);
	}
}
int main() {
	while (cin >> n){
		df(0);
		cout << su << endl;
		su = 0;
		for (int i = 0; i < 11; i++) arr[i] = 0;//更新值
	}

}

接下来再解决要输出所有方案的图的情况:参考题目链接:51. N 皇后 - 力扣(LeetCode) (leetcode-cn.com)

 当然解决本题的方法也可以用来解决上一问,但是会超时,那就也把代码给出来参考一下把(对行的cheak判断可以不用写自行删除)

#include 
using namespace std;
int con,n ;
bool cheak(int r, int l, vector>str) {
    for (int j = 0; j < n; j++)if (str[j][l] == 'H')return false;
    for (int k = 0; k < n; k++)if (str[r][k] == 'H')return false;
    // 检查 135度角是否有皇后
    for (int p = r - 1, q = l - 1; p >= 0 && q >= 0; p--, q--)
        if (str[p][q] == 'H')return false;
    // 检查 45度角是否有皇后
    for (int p = r - 1, q = l + 1; p >= 0 && q < n; p--, q++)
        if (str[p][q] == 'H')return false;
    return true;
}
void back(int r,vector>str) {
    if (r == n) {//r为当前遍历的行数
        con++; return;
    }
    for (int i = 0; i < n; i++) {
        if (cheak(r, i, str)) {//(r,i)判断该位置是否可以放入
            str[r][i] = 'H';//插入皇后
            back(r+1, str);
            str[r][i] = '.';//回溯
        }
        
    }
}
int main()
{
    while (true) {
        cin >> n; con = 0;
        vector>str(n, vector(n,'.'));//初始化
        back(0,str);//从第0行开始判断处理
        cout << con << endl;
    }
}

最后给出输出整个图的代码(思路注释中给出)

#include 
using namespace std;
int n;
vector> result;
bool cheak(int r, int l, vector< string>str) {
    for (int j = 0; j < n; j++)if (str[j][l] == 'H')return false;
    for (int k = 0; k < n; k++)if (str[r][k] == 'H')return false;
    // 检查 135度角是否有皇后
    for (int p = r - 1, q = l - 1; p >= 0 && q >= 0; p--, q--)
        if (str[p][q] == 'H')return false;
    // 检查 45度角是否有皇后
    for (int p = r - 1, q = l + 1; p >= 0 && q < n; p--, q++)
        if (str[p][q] == 'H')return false;
    return true;
}
void back(int r, vectorstr) {
    if (r == n) {//r为当前遍历的行数
        result.push_back(str); return;
    }
    for (int i = 0; i < n; i++) {
        if (cheak(r, i, str)) {//(r,i)判断该位置是否可以放入
            str[r][i] = 'H';//插入皇后
            back(r + 1, str);
            str[r][i] = '.';//回溯
        }

    }
}
int main()
{
    while (true) {
        cin >> n;
        vector str(n, string(n, '.'));//初始化
        back(0, str);//从第0行开始判断处理
        for (auto e : result) {
            for (auto s : e) {
                cout << s << " ";
            }
            cout << endl;
        }
        result.clear();
    }
}

pta n皇后(回溯/递归)_第1张图片

最后给大家提供一个很好的题目讲解以及学习的网站,跟着它给出的顺序刷题会有很大的收获,加油哦代码随想录 (programmercarl.com)

你可能感兴趣的:(pta,算法,算法)