(记录一下道阻且长的学习之路)
回溯算法
回溯算法是一种将问题的的解空间按树状图形式展开,在寻找问题的解时使用深度优先搜索策略进行遍历(暂时也不懂啥意思),并记录寻找可行解或最优解。
回溯算法一般会应用于地图路线之类的问题的解决吧
看了一下大概有以下几类
(1)装载问题 (2)0-1背包问题 (3)旅行售货员问题 (4)八皇后问题 (5)迷宫问题 (6)图的m着色问题
学习链接是https://blog.csdn.net/weiyuefei/article/details/79316653
LeetCode 52 N-Queens II(N皇后问题)
模版代码
来源:https://blog.csdn.net/Szujr/article/details/103737183?utm_source=app
(侵权联系删除)
//
// T2 N皇后问题.c
// c 191219
//
// Copyright © 2019 JaYLove0589. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#pragma warning (disable:4996)
int getMethod(const int n);
int checkPoint(int* column, const int n);
int main() {
const int MAX = 10;//说明N最大为10
const int END = 0;//说明输入0表示程序结束
int N;
while (scanf("%d", &N)) {
if (N > MAX || N < 0) {
return -1;
}
else if (N == END) {
return 0;
}
int method = getMethod(N);
printf("%d", method);
printf("\n");
}
return 0;
}
int getMethod(const int n)
{
int column[9 + 1];
// column[1]~column[n]存储n个皇后的纵坐标,其下标表示皇后的横坐标,column[0]存储皇后的总共摆法
memset(column, 0, (n + 1) * sizeof(int));//column数组置零
int method = checkPoint(column, n);//返回总共的摆法
return method;
}
int checkPoint(int* pcolumn, const int n) {//row表示当前要查找的点的行数(1~n)
static int row = 1;//查找点的起始行数为第一行
if (pcolumn[0] == 0 && pcolumn[1] == 0)
{//若pcolumn数组被置零,说明重新开始查找,将row的值初始化为1
row = 1;//
}
int flag = 0;//标志变量,值为1表示找到的皇后的点不满足条件
for (int column1 = 1; column1 <= n; column1++)
{//从row行的第1列开始寻找点,直到该行的最后一列
for (int row1 = 1; row1 < row; row1++)
{//依次与已找到的皇后点比较,若有冲突则flag=1,且continue列数
if (pcolumn[row1] == column1 || row1 - pcolumn[row1] == row - column1 || row1 + pcolumn[row1] == row + column1) {//判断该行上的点(row,column1)是否与已有的皇后点处在同一列或同一左斜线或同一右斜线
flag = 1;
break;
}
}
if (flag == 1)
{
flag = 0;
continue;
}
pcolumn[row] = column1;//若满足条件,记录该行皇后的列数(纵坐标)
row++;//因为已找到,所以进入下一行
if (row - 1 == n)
{//若找齐所有皇后的点
pcolumn[0]++;//用pcolumn[0]表示摆法的种数,种数+1
row = row - 2;//row回到倒数第2行
return pcolumn[0];
}
else
{
checkPoint(pcolumn, n);//递归算法,在row行开始寻找点
}
}
row--;//若该行所有列数都找完,都找不到满足条件的点,则回到上一行(上一层循环)
return pcolumn[0];//返回当前已找到的所有摆法
}
//思路总结:
//已知棋盘共nxn个格子,现以(1,1)为起点,(n,n)为终点。依次寻找满足条件的N个点。
//(0)若找到且已找到的点的数量为N,皇后摆法的个数加一,且返回倒数2层循环;并延续寻找,直到找到下一个满足条件的点,若没找齐返回摆法个数。
//(1)若走到尽头仍不能找齐最后一个棋子(n-1个满足条件的棋子点已找到),则返回倒数第2层循环;并延续寻找倒数第2个棋子的位置,直到找到下一个满足倒数第2个棋子摆放要求的点。—>(2)
//(2)若找到,则进入下一层循环,开始寻找下一层循环的点。若倒数第二走到尽头仍不能满足条件,则返回倒数第3层循环;并延续寻找倒数第三个棋子的点位置,直到找到下一个满足倒数第三个棋子摆放条件的点。—>(3)
//(3)若倒数第三个棋子走到尽头仍没找到,返回倒数第四个循环……
//(…)……
//(n)若第1个棋子走到尽头,仍没找到,则循环结束,返回摆法个数。
自己琢磨的(和上面的差不多)
#include <stdio.h>
#include <stdlib.h>
#pragma warning (disable:4996)
int queencol[10];
int method = 0;
void init(int* a)
{
for (int i = 0; i < 10; i++)
queencol[i] = 0;
}
int check(int n)
{
static int row = 1;//start_row
int flag = 0;
if (method == 0 && queencol[1] == 0)
row = 1;
for (int i = 1; i <= n; i++)//from col=1--col=n
{
for (int j = 1; j < row; j++)//
{
if (queencol[j] == i)//该列有皇后
{
flag = 1;
break;
}
if (j - queencol[j] == row - i || j + queencol[j] == row + i)//对角线上有皇后
{
flag = 1;
break;
}
}
if (flag == 1)//can't satisfy,look for next
{
flag = 0;
continue;
}
//satusfied,no continue and pass,note down this place
queencol[row] = i;
row++;//next col
if (row == n + 1)//all queens placed
{
method++;
row=row-2;//return last 2
return method;
}
else//not finshed,place next queen until all placed
{
check(n);
}
}
row--;//return last
return method;
}
int totalNQueens(int n)
{
method = 0;
init(queencol);
check(n);
return method;
}
int main()
{
int in;
scanf("%d", &in);
printf("%d",totalNQueens(in));
return 0;
}