首页 > 其他分享 >N皇后问题

N皇后问题

时间:2024-01-20 23:11:44浏览次数:24  
标签:ch return clock int 问题 回溯 皇后 include

问题描述:实现n皇后问题,要求利用概率算法和回溯法;只需找出一组解即可。

程序设计:

  1 #include<iostream>
  2 #include<math.h>
  3 #include <stdlib.h>
  4 #include <ctime>
  5 using namespace std;
  6 int x[100],q[100];//q[i]=n表示回溯解,x表示概率解
  7 int n,cnt = 0;
  8 clock_t start1, finish1;
  9 clock_t start2, finish2;
 10 double totaltime1,totaltime2;
 11 //回溯放置皇后时判断是否合法
 12 bool find(int a[],int k)
 13 {
 14     for(int i = 1;i < k;i++)
 15     {
 16         if(a[i] == a[k] || abs(k-i) == abs(a[k] - a[i]))
 17             return false;
 18     }
 19     return true;
 20 }
 21 bool Place(int x[],int k)
 22 {
 23     for (int i = 0;i < k;i++)
 24         if(x[i] == x[k] || abs(i - k) == abs(x[i] - x[k]))
 25         {
 26             return true;
 27         }
 28     return false;
 29 }
 30 void print(int n)
 31 {
 32     int i,j;
 33     cnt++;
 34     
 35     cout << "第 " << cnt << " 个解" << endl;
 36     
 37     for(i = 1;i <= n;i++)
 38         cout <<"(" <<  i << "," << q[i] << ")" << " ";//第i行放在第q[i]处。
 39     cout << endl;
 40     
 41     for(i = 1;i <= n;i++)        //行
 42     {
 43         for(j = 1;j <= n;j++)    //列
 44         {
 45             if(q[i] != j)
 46                 printf("x ");
 47             else
 48                 printf("Q ");
 49         }
 50         cout << endl;
 51     }
 52 }
 53 //回溯法求n皇后
 54 void queen(int n){
 55     cnt = 0;
 56     for(int i = 0;i <= n;i++)//先将所有行的列数清零
 57     {
 58         q[i] = 0;
 59     }
 60     
 61     int k = 1;//k是行数
 62     while(k >= 1)
 63     {
 64         q[k] += 1;
 65         while(q[k] <= n )//未到达最后一列
 66         {
 67             if(find(q,k))
 68                 break;
 69             else
 70                 q[k]++;//该列不行向后推一个
 71         }
 72         if(k == n && q[k] <= n)//如果到最后一行,且最后列数正确
 73         {
 74             for(int i = 1;i <= n;i++)
 75             {
 76                 cout << q[i] << " ";
 77                 
 78             }
 79             cout << endl;
 80             print(n);//将皇后以棋盘式输出
 81         }
 82         else if(q[k] <= n)//如果还没有到达最后一列,继续下一列
 83         {
 84             k++;
 85         }
 86         else//回溯,因为到达最后一行,且列数遍历完,仍没有出结果
 87         {
 88             q[k] = 0;//让该行的列数重置为0
 89             k--;//继续回到上一行
 90             
 91         }
 92     }
 93 }
 94 //类,产生随机数
 95 class RandomNumber{//类,这样才能保证不会出现产生的随机值都一样的情况。
 96 public:
 97     RandomNumber(){
 98         srand(time(0));
 99     }
100     int get(int begin = 0, int end = 1){//用这个函数可以得到随机值
101         return rand()%(end-begin+1)+begin;
102     }
103 };
104 
105 
106 bool Queen(int n) //拉斯维加斯概率求解
107 {
108     RandomNumber arr[100];
109     
110     int i,j,count=0;// //定义i,j,count. 其中count为试探次数
111     for(i = 0;i < n;)// //其中 n为行数,for循环经过n次,每次代表在第n行中找到皇后所在的列
112     {
113             //为j赋值为一个随机数,此为拉斯维加斯概率算法的核心思想,通过随机性选择快速的引导算法
114         j = arr[i + 1].get(1,n);//这样才可以保证每次的随机数都不一样,如果用j=rand()%n+1;不可以
115         
116         x[i]=j;  //将随机选取的j作为列向量参与接下来的运算
117         count++;//试探次数加一,用于确定N次运算后n列全部实验完毕
118         if(!Place(x,i))   //这个if语句用于调用冲突子函数以确定是否发生冲突,即这个位置是否可以放置皇后
119         {
120             count=0;
121             i++;
122         }
123         else if(count==n)   //位置冲突
124         {
125             return false;
126       
127         }
128         
129     }
130     
131     cout << "拉斯维加斯概率求解" << n << "皇后的一个解为" << endl;
132     
133     for(i=0;i<n;i++)//  //作为输出结果时的for循环
134     {
135        cout <<"(" <<  i + 1 << "," << x[i] << ")" << " ";
136         
137     }
138     cout << endl;
139     return true;
140 }
141 void runtime()
142 {
143     totaltime1 = finish1 - start1;
144     totaltime2 = finish2 - start2;
145     cout << "回溯法求解"<< n << "皇后的运行时间为" << totaltime1 << "毫秒" << endl;
146     cout << "拉斯维加斯概率算法求解 "<< n << "皇后的运行时间为" << totaltime2  << "毫秒"<< endl;
147 }
148 int choose()
149 {
150     int ch;
151     cout << endl << endl << endl;
152     
153     cout << "-----------------------n皇后问题---------------------" << endl;
154     cout << "                请选择你要进行的操作                   " << endl;
155     cout << "   1、回溯法求解              2、拉斯维加斯概率算法求解   " << endl;
156     cout << "   3、两种算法运行时间比较    4、退出程序              " << endl;
157     cout << "------------------------------------------------------" << endl;
158     cin >> ch;
159     return ch;
160 }
161 int main()
162 {
163     int ch = choose();
164   
165     while(ch != 4)
166     {
167         
168         switch (ch) {
169             case 1:
170                 printf("请输入皇后的个数(n <= 32),n = :");
171                 cin >> n;
172                 start1 = clock();//开始计时
173                 queen(n);
174                 finish1 = clock();
175                 break;
176                 
177             case 2:
178                 printf("请输入皇后的个数(n <= 32),n = :");
179                 cin >> n;
180                 start2 = clock();//开始计时
181                 cout << "正在重复测试,请等待······" << endl;
182                 while(!Queen(n))
183                 {
184                 }
185                 finish2 = clock();
186                 break;
187             case 3:
188                 runtime();
189                 break;
190             default:
191                 exit(0);
192         }
193       
194         ch =  choose();
195  
196     }
197     return 0;
198 }

结果输出:

 

性能测试:

依次测试n的值在4-11范围内两种算法的程序运行时间,绘制图像如下图所示:

当n=12时,用回溯法求得共有14200个解,时间明显增大:

算法时间复杂度分析:

回溯法:递归n行,每次循环n列,比较0~n - 1次

n * n * (n - 1) / 2,即O(n ^ 3),O(n * n * (n - 1) / 2) = O(n ^ 3)

拉斯维加斯概率算法:求出一组解的时候,仅需判断每次n行,比较0 ~ n - 1次,即 n * (n - 1) / 2 = O(n ^ 2)

标签:ch,return,clock,int,问题,回溯,皇后,include
From: https://www.cnblogs.com/doris510/p/17977296

相关文章

  • Linux中关于磁盘的一些常见问题小记
    1.程序导致内存不够用程序导致内存不够用如果内存满则系统会自动杀死占用内存最高的进程来保护系统正常运行什么原因导致内存满:1.大量用户访问服务器(正常情况)需要我们添加内存2.由于程序导致内存满,而不是大量用户访问导致(找开发解决)3.由于网络的波动导致内存满需要......
  • 使用CGO要注意的问题
    密码学有很多较快的算法是基于c或c++纂修,而工程上主要以go语言为主,在此梳理一些go调用c常见问题和用例。有很多奇特的方式进行传输,但是想要性能最优还是以指针传输作为主要传输方式。一些简单的计算可以直接使用c编写成.h进行引用,但在工程部署常常拥有大量依赖库,若在服务......
  • 加权区间调度问题
    问题描述:给定n个job,每个活动i的开始时间和结束时间,对应一个权值,找出权值之和最大的相容活动子集。(若两个job的时间不相交,则称两个活动是相容的compatible)方案一(递归算法)算法设计:OPT(j): //j个活动求相容活动子集的最大权值    If j == 0 thenreturn 0Elsereturn max......
  • P8651 [蓝桥杯 2017 省 B] 日期问题
    这道题虽然逻辑很简单,但是坑不少,一不留神就WA了要记得去重+排序#include<iostream>#include<stdio.h>#include<algorithm>#include<string>#include<set>#defineFor(i,j,n)for(inti=j;i<=n;++i)usingnamespacestd;stringdate;set<......
  • 比赛日程问题
    问题描述:1.设有n(n为任意值)个选手进行循环赛,手工设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次;(2)每个选手一天只能赛一次;(3)循环赛一共进行n-1天。算法设计:假设有N名选手参赛,不妨构造一个N×N的矩阵。在矩阵第一行填充1,2,…,N,第一列填充1,2,…......
  • 热血江湖服务端开服遇到的小问题详解
    热血江湖服务端开服遇到的小问题详解大家好我是艾西,今天跟大家分享下你们自己在搭建热血江湖或是开服过程中会遇到的小问题以及常用到的一些指令都是什么意思,有了一定的基础了解在后期您干起来肯定会更加的得心应手!出现ODBC链接不了:出现ODBC数据库配置连接失败的问题,可能是由于以下......
  • 记录一下 ArrayBlockingQueue 消息堆积的问题
    前言由于之前这个系统的日志记录是被领导要求写表的,在不影响系统性能的前提下,日志的入库操作肯定是要改成异步进行的,当时利用ArrayBlockingQueue+线程+AOP简单的去实现了一下,但是初版代码测试下来发现了一个很严重的问题,就是日志丢失的问题,本文由此而来。初步构思代码实现逻辑实......
  • VC 编译crt不同版本,Debug/Release混用问题
    extern"C" int__CRTDECL_imp__swprintf( _Pre_notnull__Post_z_wchar_t*const_Buffer, _In_size_tconst_BufferCount, _In_z__Printf_format_string_wchar_tconst*const_Format, ...){ int_Re......
  • SpringBoot项目通过注解快速解决,字典翻译,响应数据加密,数据脱敏等问题
    简介在几乎所有SpringBoot项目中都会面临字典翻译,接口数据加密,数据脱敏的问题。在每个接口中单独的解决会非常繁琐,因此接下来介绍一下怎么通过注解快速解决这些问题。实现步骤1.引入maven坐标<dependency><groupId>io.gitee.gltqe</groupId><artifactId>......
  • spring--是如何解决单例模式下循环依赖问题的
    Spring解决单例bean的循环依赖主要依赖于容器的三级缓存机制,以及bean的提前暴露。这里是它如何工作的:三级缓存:一级缓存(singletonObjects):存储已经经过完整生命周期处理的单例bean,包括初始化和依赖注入等。二级缓存(earlySingletonObjects):存储早期的单例对象的引用,这些......