算法分析与设计(满足方程解问题+4皇后问题)

一、实验目的

  1. 掌握回溯法算法框架,掌握分枝限界法的特点和算法框架。
  2. 熟练掌握“满足方程解问题求解算法”的实现,熟练掌握“4皇后问题求解算法”的实现。
  3. 主要任务:实现教材配套实验指导书“第2章 2.5.4小节 求解满足方程解问题”和“第2章 2.6.1小节 求解4皇后问题”。

二、使用仪器、材料

PC微机;

Windows 操作系统,VS2015编译环境(不限);

三、实验步骤

  • 复习回溯法和分支限界法的思想
  • 完成题目求解方程解问题
  • 调试代码,验证代码正确性并分析时间复杂性
  • 完成4皇后问题的求解
  • 调试代码,验证代码正确性并分析时间复杂性

四、实验过程原始记录(数据、图表、计算等)

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!),本题规模较小,因此时间复杂度在可承受的范围内。

  1. 求解4皇后问题

本题利用分支限界法, 以广度优先的方式进行搜索,分为队列式和优先队列式。队列式是将当前结点所有可能的子结点都加入队列,按照先进先出的原则(出队结点编号是连续的),出队并且分析出队结点有无子结点。优先队列式是将队列中的结点按照结点对应的行号建立大根堆(出队结点的编号是跳跃的),行号越大,越先出队列进行分析。

具体求解代码如下:

队列式:

#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),但由于皇后问题的约束,并不需要遍历所有的情况,当某一行没有合适的位置放置皇后时,就直接返回上层,试探别的情况。另外,对于优先级队列式,行号大的结点优先出队,从而提高了效率。

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值