赞
踩
n
!
=
{
1
n
=
0
n
∗
(
n
−
1
)
!
n
>
0
n!=
#include <stdio.h>
int fact(int n) {
if (n == 0) return 1;//边界
return n * fact(n - 1);//公式
}
int main() {
int ans = fact(10); //调用
printf("%d\n", ans);
return 0;
}
Fibonacci sequence:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ……
f
(
n
)
=
{
0
n
=
0
1
n
=
1
f
(
n
−
2
)
+
f
(
n
−
1
)
n
>
1
f(n)=
#include <stdio.h>
int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fib(n - 1) + fib(n - 2);
}
int main() {
for (int i = 0;i < 10;i++) {
printf("%d ", fib(i));
}
printf("\n");
return 0;
}
gcd(12, 32) = 4
gcd(a, b)
gcd(32, 12)
gcd(12, 8)
gcd(8, 4)
gcd(4, 0)
g
c
d
(
a
,
b
)
=
{
a
b
=
0
g
c
d
(
b
,
a
%
b
)
b
≠
0
gcd(a,b)=
//辗转相除法
#include <stdio.h>
int gcd(int a, int b) {
if (b == 0)return a;
return gcd(b, a % b);
}
int main() {
printf("%d ", gcd(12, 32));
}
分治法的设计思想:
题目描述:
一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法。
第一行输入T,表示有多少个测试数据。接下来T行,每行输入一个数n,表示台阶的阶数。
输出时每一行对应一个输出。
样例输入:
3
5
8
10
样例输出:
8
34
89
解析:
f
(
n
)
=
{
1
n
=
1
2
n
=
2
f
(
n
−
1
)
+
f
(
n
−
2
)
n
>
2
f(n)=
参考代码:
#include <stdio.h> int solve(int n) { if (n == 1) return 1; if (n == 2) return 2; //列如:solve(5) //从1->2级:即先采用‘跳一级’策略,后面4级台阶的总跳法为solve(4)个 //从1->3级:即先采用‘跳两级’策略,后面3级台阶的总跳法为solve(3)个 return solve(n - 1) + solve(n - 2); } int main() { //int T; //scanf_s("%d", &T);//设置测试数 //while (T--) { // int n; // scanf_s("%d", &n);//设置台阶数 int ans = solve(5); printf("%d\n", ans); return 0; }
#include <iostream> using namespace std; void mergeArray(int A[], int l, int mid, int r) { int* temp = new int[r - l + 1]; int i = l, j = mid + 1;//i指向‘前半段’首索引,j指向‘后半段’首索引 int k = 0;//临时temp[]首索引 //给临时temp[]赋‘A[]前半段’ while (i <= mid && j <= r) { if (A[i] <= A[j])temp[k++] = A[i++]; else temp[k++] = A[j++]; } //给临时temp[]赋‘A[]后半段’ while(j <= r)temp[k++] = A[j++]; while (i <= mid)temp[k++] = A[i++]; //通过临时temp[]赋A[],使A[]得到真正排序 for (int i = l, k = 0;i <= r;i++, k++) { A[i] = temp[k]; } delete temp; } //归并排序 void mergesort(int A[], int l, int r) { if (l >= r) return; int mid = l + (r - l) / 2; mergesort(A, l, mid);左半区间[lo, mid] 排好序 mergesort(A, mid+1, r);右半区间[mid + 1, hi] 排好序 mergeArray(A, l, mid, r);//进行合并 } int main() { int A[] = { 6,1,2,9,7,3 }; int N = sizeof(A) / sizeof(int); mergesort(A, 0, N - 1); for (int x : A) { cout << x << " "; } cout << endl; return 0; }
二叉树节点在水平方向上的投影顺序即为中序遍历的顺序。
#include <iostream> #include <queue> #include <algorithm> using namespace std; struct Node { int data; Node * lchild, * rchild; Node(int x = 0) { data = x;lchild = rchild = NULL; } void setChildNode(Node *l,Node *r) { lchild = l; rchild = r; } }; void preorderTrav(Node * root){ if (root == NULL)return; printf("%d", root->data);//先序遍历:先访问根节点 preorderTrav(root->lchild); preorderTrav(root->rchild); } void inorderTrav(Node * root) { if (root == NULL)return; inorderTrav(root->lchild); printf("%d", root->data);//中序遍历:中间访问根节点 inorderTrav(root->rchild); } void postoderTrav(Node* root) { if (root == NULL)return; postoderTrav(root->lchild); postoderTrav(root->rchild); printf("%d", root->data);//后序遍历:最后访问根节点 } //层次遍历讲解:https://www.bilibili.com/video/BV1S54y1Y7Uq?from=search&seid=2361716283609621762&spm_id_from=333.337.0.0 // A // B C //D E F G //层次遍历(有条件的先序遍历,key:*t<=>Node[N];从而更好的访问不断变化的队顶元素) void levelTrav(Node* root) { if (root == NULL)return; //建立队列Q queue <Node*> Q; //根节点入队('A') Q.push(root); //循环出队,入队===================================>⑤当队列为空时返回true,退出循环 while (Q.empty() != true) { //访问队顶元素①('A')====>②('B')====>③('C')====>④('DEFG') Node *t = Q.front(); //移除并打印队顶元素①('A')====>②('B')====>③('C')====>④('DEFG') Q.pop(); printf("%d", t->data); //左子树入队①('B')====>②('D')====>③('F')====>④pass if (t->lchild != NULL)Q.push(t->lchild); //右子树入队①('C')====>②('E')====>③('G')====>④pass if (t->rchild != NULL)Q.push(t->rchild); } printf("\n"); } int getTreeHigh(Node* root) { if (root == NULL)return 0; int LHigh = getTreeHigh(root->lchild); int RHigh = getTreeHigh(root->rchild); return max(LHigh, RHigh)+1; } int main() { Node *root = new Node(1); Node * Node2 = new Node(2); Node * Node3 = new Node(3); Node * Node4 = new Node(4); Node * Node5 = new Node(5); Node * Node6 = new Node(6); Node * Node7 = new Node(7); Node * Node8 = new Node(8); // 1 // 2 3 // 4 5 null 7 //null 8 6 null root->setChildNode(Node2, Node3); Node2->setChildNode(Node4, Node5); Node3->setChildNode(NULL, Node7); Node4->setChildNode(NULL, Node8); Node5->setChildNode(Node6, NULL); preorderTrav(root); printf("\n"); inorderTrav(root); printf("\n"); postoderTrav(root); printf("\n"); levelTrav(root); printf("\n"); printf("Tree Height: %d\n", getTreeHigh(root)); }
表达式树的特征:叶节点是运算数,非叶节点一定是运算符!
输入格式:
第一行给出节点的个数N,每个节点的编号为0 ~ N-1
接下来N行每行分别给出:
该节点的编号、该节点的操作数/操作符、该节点的左孩子编号、右孩子编号(-1表示NULL)
输出格式:
第一行输出该表达式树的中缀表达式,该用括号的地方需要用括号括起来。
第二行输出该表达式树的前缀表达式。
第二行输出该表达式树的后缀表达式。
第四行输出该表达式树的计算结果,保留两位小数。
样例输入:
11
0 - 1 2
1 + 3 4
2 / 5 6
3 4 -1 -1
4 * 7 8
5 6 -1 -1
6 3 -1 -1
7 1 -1 -1
8 - 9 10
9 5 -1 -1
10 2 -1 -1
样例输出:
(4+(1*(5-2)))-(6/3)
- + 4 * 1 - 5 2 / 6 3
4 1 5 2 - * + 6 3 / -
5.00
完整代码:
#include <iostream> using namespace std; //二叉树组成:运算数(叶结点)+运算符(其他) struct Node{ char data; Node* lchild, * rchild; }; //前缀表达式(前序遍历) void preOrder(Node* root) { if (root == NULL) return; printf("%c ", root->data); preOrder(root->lchild); preOrder(root->rchild); } //后缀表达式(后续遍历) void postOrder(Node *root) { if (root == NULL) return; postOrder(root->lchild); postOrder(root->rchild); printf("%c ", root->data); } //中缀表达式(有条件的中序遍历) void inOrder(Node *root,int layer){ if (root == NULL)return; //输出目标结果:(4 + (1 * (5 - 2))) - (6 / 3) //注释:若无此条件语句,输出结果:(( (4)+( (1)*( (5)-(2) )))-( (6)/(3) )); if (root->lchild == NULL && root->rchild == NULL) printf("%c", root->data);//操作对象:叶结(束)点 else { if (layer > 0)printf("("); //注释:若无此(int layer)参数引入,输出结果:(( 4+( 1*( 5-2 )))-( 6/3 )); inOrder(root->lchild,layer+1); printf("%c",root->data); inOrder(root->rchild,layer+1); if (layer > 0)printf(")"); } } //计算函数 double calc(double a, double b, char op) { switch (op){ case '+':return a + b; case '-':return a - b; case '*':return a * b; case '/':return a / b; } } //递归算法:返回计算结果 double calcExprTree(Node *root) { if (root == NULL)return 0; //当递到最后一层(递归边界条件):即全是叶结点时,‘5’->5,'2'->2; if (root->lchild == NULL && root->rchild == NULL)return root->data - '0';//对象:叶结点 double a = calcExprTree(root->lchild); double b = calcExprTree(root->rchild); //计算5-2,并开始归,归到到第一层,返回最终结果; return calc(a, b, root->data); } //自定义交互界面:&索引0-10;&对应索引元素值; //&对应索引的左子节点索引(-1代表NULL);&对应索引的右子节点索引(-1代表NULL); //样例输入(在自定义交互界面): // 11 // 0(空格)-(空格)1(空格)2 // 1 + 3 4 // 2 / 5 6 // 3 4 - 1 - 1 // 4 * 7 8 // 5 6 - 1 - 1 // 6 3 - 1 - 1 // 7 1 - 1 - 1 // 8 - 9 10 // 9 5 - 1 - 1 // 10 2 - 1 - 1 // 样例输出: // (4 + (1 * (5 - 2))) - (6 / 3)(中缀表达式) // - +4 * 1 - 5 2 / 6 3(前缀表达式) // 4 1 5 2 - *+6 3 / -(后缀表达式) // 5.00 int main() { //通过用户交互界面,定义总节点数N(含根节点); int N; scanf("%d/n", &N); //*nodes[N]<=>树结构Node[索引及对应元素值]; Node* nodes = new Node[N]; //赋值*nodes[N]:通过循环结构及用户交互界面; for (int i = 0;i < N;i++) { int index; char data; int l, r; //用户交互界面; scanf("%d %c %d %d",&index, &data, &l, &r); //赋值; nodes[index].data = data; nodes[index].lchild = (l != -1 ? &nodes[l] : NULL); nodes[index].rchild = (r != -1 ? &nodes[r] : NULL); } Node *root = &nodes[0]; inOrder(root, 0); printf("\n"); preOrder(root); printf("\n"); postOrder(root); printf("\n"); double ans = calcExprTree(root); printf("%.2f\n",ans); return 0; }
对于如下二叉树,节点7
位于第4
层,其到跟节点的路径为1 2 5 7
先把问题简化一下,求二叉树指定节点所在层数(假设根节点的层数为1)
为了记录当前访问节点的层号,对于层号,可以采用以下两种方式:
对于如下二叉树,节点7
位于第4
层,其到跟节点的路径为1 2 5 7
#include <iostream> #include <vector> using namespace std; struct Node { int data; Node* lchild, * rchild; Node(int x = 0) { data = x;lchild = rchild = NULL; } void setChildNode(Node* l, Node* r) { lchild = l; rchild = r; } }; /求该节点所在层数/// //方法一:使用全局变量(int layer=0;堆空间) int layer = 0;//key1 bool flag1 = false; //前序遍历架构 void getNodeLayer(Node* root, int x) { if (root == NULL)return; //找到x后,flag1用于提前结束递归执行; if (flag1)return; //根节点层为1; layer++;//key2 if (root->data == x) { printf("%d\n", layer); flag1 = true; return; } getNodeLayer(root->lchild, x); getNodeLayer(root->rchild, x); //每次遍历到末尾,层数减一;再进行到下次遍历,层数再依次加一 layer--;//key3 } //方法二:使用函数传参(值传递:getNodeLayer(root, x, layer + 1) ); // getNodeLayer(root, 7, 1);//key1 //bool flag1 = false; //void getNodeLayer(Node* root, int x, int layer) {//key2 // if (root == NULL)return; // // if (flag1 == true)return; // if (root->data == x) { // printf("%d", layer); // flag1 = true; // return; // } // getNodeLayer(root->lchild, x, layer + 1);//key3 // getNodeLayer(root->rchild, x, layer + 1);//key4 //} //方法三:使用函数传参(传指针/引用:int &layer栈空间)(了解) //bool flag1 = false; //void getNodeLayer(Node* root, int x, int & layer) {//key3 // if (root == NULL)return; // // layer++;//key4 // if (root->data == x) { // printf("%d", layer); // flag1 = true; // return; // } // getNodeLayer(root->lchild, x, layer); // getNodeLayer(root->rchild, x, layer); // // layer--;//key5 //} //方法四:将递归函数封装(了解) //void getNodeLayer(Node *root, int x, int &layer, int &ans, bool &flag1) {//key3 // if (root == NULL)return; // // layer++;//key4 // if (flag1 == true)return; // if (root->data == x) { // ans = layer; // flag1 = true; // return; // } // getNodeLayer(root->lchild, x, layer, ans, flag1); // getNodeLayer(root->rchild, x, layer, ans, flag1); // // layer--;//key5 //} //int getNodeLayer(Node* root, int x) { // //key1(定义引用变量) // int ans; // int layer = 0; // bool flag1= false; key2 // getNodeLayer(root, x,layer,ans, flag1); // //key6(输出“接口”) // return ans; //} /求节点路径(类似求该节点所在层数) //方法一:使用全局数组 vector<int>path;//key1全局数组 bool flag2 = false; void getNodePath(Node* root, int x) { if (root == NULL)return; if (flag2)return; path.push_back(root->data);//key2入栈 if (root->data == x) { for (int x : path) {C++11特性:范围的For循环(range-based-for) printf("%d ", x);//key3输出栈 } flag2 = true; return; } getNodePath(root->lchild, x); getNodePath(root->rchild, x); path.pop_back();//key4出栈 } //方法二:使用函数传参(传指针/引用) //bool flag2 = false; //void getNodePath(Node* root, int x, vector<int>& path) {//key3 指针数组 // if (root == NULL)return; // // if (flag2)return; // path.push_back(root->data);//key4 // if (root->data == x) { // for (int x : path) { // printf("%d ", x);//key5 // } // flag2 = true; // return; // } // getNodePath(root->lchild, x, path); // getNodePath(root->rchild, x, path); // // path.pop_back();//key6 //} //方法三:使用函数传参(值传递) 不推荐(∵每次递归调用,会对path数组进行复制∴时间和空间效率低) //bool flag2 = false; //void getNodePath(Node* root, int x, vector<int>path) {//key3 // if (root == NULL)return; // // if (flag2)return; // path.push_back(root->data); // if (root->data == x) { // for (int x : path) { // printf("%d ", x); // }//key4 // flag2 = true; // return; // } // getNodePath(root->lchild, x, path); // getNodePath(root->rchild, x, path); // //无path.pop_bach() //} int main() { Node* root = new Node(1); Node* node_2 = new Node(2); Node* node_3 = new Node(3); Node* node_4 = new Node(4); Node* node_5 = new Node(5); Node* node_6 = new Node(6); Node* node_7 = new Node(7); Node* node_8 = new Node(8); root->setChildNode(node_2, node_3); node_2->setChildNode(node_4, node_5); node_3->setChildNode(NULL, node_6); node_5->setChildNode(node_7, NULL); node_7->setChildNode(NULL, node_8); /求该节点所在层数/ //方法一 int x = 7; getNodeLayer(root, x); //方法二 //getNodeLayer(root, 7,1); //方法三 //int layer=0;//key1 // getNodeLayer(root, 7,layer);//key2 //方法四 //int getNodeLayer(Node * root, int x) { // //key1(定义引用变量) // int ans; // int layer = 0; // bool flag1 = false; // //key2 // getNodeLayer(root,x,layer,ans,flag1) //} // /求节点路径(类似求该节点所在层数) //方法一 getNodePath(root, x); printf("\n"); //方法二 //key1定义引用变量 //int x = 7; //vector<int>path; key2 //getNodePath(root, x, path); //方法三 //key1 //int x = 7; //vector<int>path; //key2 //getNodePath(root, x, path); return 0; }
写法一:vector<int> vec {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < vec.size(); i++){
printf("%d ", vec[i]);
}
//C++11特性:范围的For循环(range-based-for)
写法二:for (int x : vec) { //这样写对于容器内的每个元素是只读的
printf("%d ", x);
}
#include <iostream> #include <vector> #include <queue> #include <initializer_list> using namespace std; struct Node { int data; //key1利用指针数组,存放多分支 vector<Node*>child; Node(int x = 0) { data = x; } void setChildNode(initializer_list<Node*>list) {//C++11特性:initializer_list(传入列表数据,分别代表各分支节点) //key2利用循环及指针数组,建立多分支 for (Node* x : list) { child.push_back(x); } } }; //先序遍历 void preOrder(Node* root) { if (root == NULL)return; printf("%d", root->data); //key3利用循环及指针数组,进行递归 for (Node* x : root->child) { preOrder(x); } } //后序遍历 void postOrder(Node* root) { if (root == NULL)return; //key3 for (Node* x : root->child) { preOrder(x); } printf("%d", root->data); } //层次遍历 void levelOrder(Node* root) { if (root == NULL)return; queue<Node*> Q;//建队 Q.push(root);//入队 while(Q.empty() == false) { Node* t = Q.front();Q.pop();//出队 //key4:利用*t<=>Node*,来进行队顶元素的变换 printf("%d", t->data);//打印队顶节点元素 for (Node* x : t->child) { Q.push(x);//入队:相应队顶节点的子节点 } } } int main() { Node* root = new Node(1); Node* node_2 = new Node(2); Node* node_3 = new Node(3); Node* node_4 = new Node(4); Node* node_5 = new Node(5); Node* node_6 = new Node(6); Node* node_7 = new Node(7); Node* node_8 = new Node(8); Node* node_9 = new Node(9); Node* node_10 = new Node(10); root->setChildNode({ node_2,node_3,node_4 }); node_2->setChildNode({ node_5,node_6,node_7 }); node_4->setChildNode({ node_8 }); node_8->setChildNode({ node_9,node_10 }); preOrder(root); printf("\n"); postOrder(root); printf("\n"); levelOrder(root); printf("\n"); return 0; }
函数调用栈实例:主函数main()
调用funcA()
,funcA()
调用funcB()
,funcB()
再自我调用(递归)
函数调用栈的基本单位是帧(frame)。每次函数调用时,都会相应地创建一帧, 记录该函数实例在二进制程序中的返回地址(return address),以及局部变量、传入参数等, 并将该帧压入调用栈。若在该函数返回之前又发生新的调用,则同样地要将与新函数对应的一帧压入栈中,成为新的栈顶。函数一旦运行完毕,对应的帧随即弹出,运行控制权将被交还给该函 数的上层调用函数,并按照该帧中记录的返回地址确定在二进制程序中继续执行的位置。
在任一时刻,调用栈中的各帧,依次对应于那些尚未返回的调用实例,亦即当时的活跃函数实例(active function instance)。特别地,位于栈底的那帧必然对应于入口主函数main(), 若它从调用栈中弹出,则意味着整个程序的运行结束,此后控制权将交还给操作系统。
此外,调用栈中各帧还需存放其它内容。比如,因各帧规模不一,它们还需记录前一帧的起始地址,以保证其出栈之后前一帧能正确地恢复。
作为函数调用的特殊形式,递归也可借助上述调用栈得以实现。比如在上图中,对应于 funcB()
的自我调用,也会新压入一帧。可见,同一函数可能同时拥有多个实例,并在调用栈中 各自占有一帧。这些帧的结构完全相同,但其中同名的参数或变量,都是独立的副本。比如在 funcB()
的两个实例中,入口参数m
和内部变量i
各有一个副本。
如果某问题的解可以由多个步骤得到,而每个步骤都有若干种选择(这些候选方案集可能会依赖之前做出的选择),且可以用递归枚举法实现,则它的工作方式可以用解答树来描述。
输出数字1~N所能组成的所有全排列
#include <iostream> #include <vector> using namespace std; const int MAXn = 10; bool isused[MAXn];//使用检验 vector<int>num;//设置num数组 int N;//数据范围(1-3) void DFS(int index){ //每次递归的边界条件 if (index >= N) { for (int x : num) { printf("%d", x); } printf("\n"); return; } //核心思想讲解:https://www.bilibili.com/video/BV1ct411u7Qi?from=search&seid=11426884062134919798&spm_id_from=333.337.0.0 for (int i = 1;i <= N;i++) { if (isused[i])continue; //①1入队(index=0处) num.push_back(i); //②设置1已经used isused[i] = true; //③index=1->n-2做全排列 DFS(index + 1); //④1出队 num.pop_back(); //⑤设置1未used isused[i] = false; } } int main() { N = 3; DFS(0);//输入0层 return 0; }
将1到n这n个整数围成一个圆环,若其中任意2个相邻的数字相加,结果均为素数,那么这个环就成为素数环。
例如数字1-6所组成的一个素数环,用数组表示是[1, 4, 3, 2, 5, 6]
(第一位固定为1)
#include <iostream> #include <vector> #include <algorithm> using namespace std; const int MAXN = 100; bool isPrimeNum[MAXN];/key1 质数检验 bool isUsed[MAXN];//使用检验 vector<int> num;//ans数组 int N;//数据范围(1-4) ///key2 筛选法求质数 void getPrimeTable() { //先假设都是素数 fill(isPrimeNum, isPrimeNum + MAXN, true);//设置拼接数组,值为true isPrimeNum[0] = isPrimeNum[1] = false;//并定义0,1为非质数 for (int i = 2;i < MAXN;i++) { if (isPrimeNum[i]) { /key3 若i是质数:把i的倍数全部设置成非质数(质数的整数倍不是质数); for (int j = i+i; j < MAXN;j += i) {//key2 j+=i; isPrimeNum[j] = false; } } } } void DFS(int index) { //递归边界条件 if (index >= N) { key4 判断第一个数和最后一个数相加后是否为质数; int temp = num[0] + num[index - 1];key4-1 这里的index-1为尾元素索引; if (isPrimeNum[temp] == false)return; //若是:打印数组 for (int x : num) { printf("%d", x); } printf("\n"); return; } for (int i = 2;i <= N;i++) { if (isUsed[i])continue; //剪枝:若相邻元素和不为质数,直接跳出循环; int temp = i+ num[index - 1]; //key4-2 这里的index-1为相邻元素索引; if (isPrimeNum[temp] == false) { continue; } num.push_back(i); isUsed[i] = true; DFS(index + 1); num.pop_back(); isUsed[i] = false; } } int main() { getPrimeTable(); N = 4; num.push_back(1); DFS(1); return 0; }
八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当n = 1或n ≥ 4时问题有解。
#include <cstdio> #include <algorithm> using namespace std; const int MAXN = 100; int solution[MAXN];//记录i行中皇后位置j int cnt;//总方法数 int N;//N皇后 //key1 定义棋盘,以用于各种方法的可视化显示 char chessboard[MAXN][MAXN]; void printSolution() { fill(chessboard[0], chessboard[0] + MAXN * MAXN,'*');//初始化棋盘为* //通过for循环:查找棋盘上所有皇后位置j->定义所有皇后位置为# for (int i = 0;i < N;i++) { int j = solution[i];//查找:通过solution[i],查找第i行中皇后位置j chessboard[i][j] = '#';//定义:查找后,定义皇后位置为# chessboard[i][N] = '\0'; } printf("solution #%d\n", cnt); //通过for循环:打印*棋盘及所有#皇后 for (int i = 0;i < N;i++) { printf("%s\n", chessboard[i]);//打印:*棋盘及#皇后 } printf("\n"); } //key2 判断(row,col)位置是否处在所有前皇后的攻击范围。若处于,则返回false; bool judge(int row, int col) { //通过for循环:查找前row行所有皇后位置j,并判断(row,col)位置是否处于攻击位置 for (int i = 0;i < row;i++) { //查找:通过solution[i],查找第i行中皇后位置j int j = solution[i]; //判断:同列、斜线(副对角、主对角) //注:不需要同行检查---在单层搜索的过程中,每一层递归,只会选for循环(也就是同一行)里的一个元素,所以不用去重了。) if (j == col || row + col == i + j || row - col == i - j) return false; } return true; } void DFS(int row) { //每次递归的边界条件 if (row >= N) { cnt++;//成功递归一次,意味着多一种解法; printSolution();//可视化该解法 return; } //核心 for (int col = 0;col < N;col++) { //冲突:下循环 if (judge(row, col) == false)continue; //不冲突:solution[row]=col,即定义第row行的皇后位置为col; solution[row] = col; DFS(row + 1);//每一层递归,只会选for循环(也就是同一行)里的一个元素 } } int main() { N = 8; DFS(0); printf("N=%d,total solutions:%d\n", N, cnt); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。