一、实验目的
二、使用仪器、材料 PC微机; Windows 操作系统,VS2015编译环境(不限); 三、实验步骤
|
四、实验过程原始记录(数据、图表、计算等) 1. 求解方程解问题 本题采用回溯法的思想,采用深度优先遍历的搜索方式,利用交换的方法,交换当前结点解向量中的值,来达到找出1-5数字所有可能的排列方式并检验这种排列方式是否满足最后求解的要求。 具体求解代码如下: #include<iostream> using namespace std; #define MAXN 6 int x[MAXN]; bool w[MAXN] = { false }; int n = 5; void swap(int& a, int& b) { int temp = a; a = b; b = temp; } void dfs(int m) { if (m >= n) { int a = x[1]; int b = x[2]; int c = x[3]; int d = x[4]; int e = x[5]; if (a * b - c * d - e == 1) { for (int i = 1; i <= n; i++) { cout << x[i] << " "; } cout << endl; } } else { for (int j = m; j <= n; j++) { swap(x[m], x[j]); dfs(m + 1); swap(x[m], x[j]); } } } int main() { for (int i = 1; i <= n; i++) { x[i] = i; } cout << "abcde的取值分别为" << endl; dfs(1); cout << endl; } 时间复杂度分析: 本题采用回溯法的思想,利用穷举所有的排列情况,因此时间复杂度为O(n!),本题规模较小,因此时间复杂度在可承受的范围内。
本题利用分支限界法, 以广度优先的方式进行搜索,分为队列式和优先队列式。队列式是将当前结点所有可能的子结点都加入队列,按照先进先出的原则(出队结点编号是连续的),出队并且分析出队结点有无子结点。优先队列式是将队列中的结点按照结点对应的行号建立大根堆(出队结点的编号是跳跃的),行号越大,越先出队列进行分析。 具体求解代码如下: 队列式: #define MAXN 5 int n = 4; struct Node { int no; int row; int x[MAXN]; }; int count = 1; bool judge(Node e, int m) {//判断是否能够放置皇后 for (int i = 1; i < e.row; i++) { if (m == e.x[i]) { return false; } } if (m - 1 == e.x[e.row - 1] || m + 1 == e.x[e.row - 1]) return false; return true; } void bfs(int row) { Node e, e1; e.row = row; queue <Node> q; for (int i = 1; i <= n; i++) { e.no = count++; e.x[row] = i; q.push(e); } while (!q.empty()) { e = q.front(); q.pop(); cout << "出队行号为" << e.row << "编号为" << e.no << endl; if (e.row == n) {//找到一个可行解 cout << "从第一行至第4行,皇后放置的列号为"; for (int i = 1; i <= n; i++) { cout << e.x[i] << " "; } cout << endl; continue; } for (int i = 1; i <= e.row; i++) { e1.x[i] = e.x[i]; } e1.row = e.row + 1; for (int i = 1; i <= n; i++) { if (judge(e1, i)) { e1.no = count++; e1.x[e1.row] = i; cout << "入队结点" << e1.row << " " << e1.x[e1.row] << endl; q.push(e1); } } } } 输出结果: 优先队列式: #define MAXN 5 int n = 4; int count = 1; struct Node { int no; int row; int x[MAXN]; bool operator<(const Node& e)const { return row < e.row; } }; bool judge(Node e, int m) { for (int i = 1; i < e.row; i++) { if (m == e.x[i]) { return false; } } if (m - 1 == e.x[e.row - 1] || m + 1 == e.x[e.row - 1]) return false; return true; } void bfs(int row) { Node e, e1; e.row = row; priority_queue <Node> q; for (int i = 1; i <= n; i++) { e.no = count++; e.x[row] = i; q.push(e); } while (!q.empty()) { e = q.top(); q.pop(); cout << "出队行号为" << e.row << "出队编号为" << e.no << endl; if (e.row == n) { cout << "从第一行至第4行,皇后放置的列号为"; for (int i = 1; i <= n; i++) { cout << e.x[i] << " "; } cout << endl; continue; } for (int i = 1; i <= e.row; i++) { e1.x[i] = e.x[i]; } e1.row = e.row + 1; for (int i = 1; i <= n; i++) { if (judge(e1, i)) { e1.no = count++; e1.x[e1.row] = i; q.push(e1); cout << "入队" << e1.row << " " << i << endl; } } } } 输出结果: 时间复杂度分析:本题采用分支限界法的思想求解问题,共递归n层,最坏情况,时间复杂度为O(n^n),但由于皇后问题的约束,并不需要遍历所有的情况,当某一行没有合适的位置放置皇后时,就直接返回上层,试探别的情况。另外,对于优先级队列式,行号大的结点优先出队,从而提高了效率。 |