基于C语言的n皇后问题
1.逻辑梳理
- 1.利用回溯法解决N皇后问题,逐行和逐列查找满足条件的位置
- 2.如果一整行都找不到满足条件的位置,那么回溯到上一行
- 3.解决N皇后问题,就是建立N*N的矩阵,但是N皇后超过20对电脑要求比较高
- 4.N皇后问题中,需要满足三个约束条件,不在同一行、同一列、同一斜线
- 5.当N=2,3时都受到约束条件的限制
- 6.在queens函数中调用dispasoulution(n);函数,实现输出解功能。place(k);函数实现确定皇后放置位置问题
- 7.在主函数中,用户从键盘输入n值,通过判断用户输入值的可行性,给出合理建议。
2.逻辑开发
2.1 dispasoulution函数 - void dispasoulution(int n)//输出一个解
- {
- static int count=0;//定义静态变量来统计解的个数
- int i;
- printf("第%d个解:",++count);//每输出一次执行一次++
- for(i=1;i<=n;i++)
- printf("(%d,%d)",i,q[i]);//利用for循环依次输出解
- printf("\n");
- }
复制代码
2.2 place函数 - int place(int k)//调用place函数判断能否放置该皇后
- {
- int i=1;
- while(i<k)
- {
- if((q[i]==q[k])||(abs(q[i]-q[k])==abs(i-k)))//判断是否满足约束关系,不能同列,不能同对角线
- return 0;
- i++;
- }
- return 1;
- }
复制代码
2.3 queens函数 - void queens(int n)
- {
- int k=1;//表示皇后个数或行数
- q[k]=0;//表示当前列,从开头存放
- while(1)
- {
- q[k]=q[k]+1;//测试下一列
- while(q[k]<=n&&!place(k))
- q[k]=q[k]+1;
- if(q[k]<=n)//找到第k个皇后的合适位置
- {
- if(k==n)//(皇后全部放置)
- dispasoulution(n);//当满足k==n时,输出这个解
- else
- {
- k++;//向下一行放置皇后
- q[k]=0;//从第一列开始
- }
- }
- else//如果没有找到合适的存放皇后的位置
- {
- if(k==1) exit(0);//如果回溯完成,算法结束
- k--;//回溯到上一行
- }
- }
-
- }
复制代码
2.4 again函数 - void again()
- {
- int n;
- printf("请重新输入一个合适的N值:\n");
- scanf("%d",&n);
- if(n==1&&n>=4||n<=20)
- queens(n);
- else
- printf("禁止再次输入\n");
- }
复制代码
2.5 主函数 - int main()
- {
- int n;
- printf("n皇后问题(n<20)\nn=");
- scanf("%d",&n);
- if(n>1&&n<4||n>20)
- {
- printf("n值不满足情况!\n");
- again();
- }
- else
- {
- printf("n皇后的问题求解如下:\n");
- queens(n);
- }
- }
复制代码
3.完整代码 - #include<stdio.h>
- #include<stdlib.h>
- const int MAXN=20;//表示最多存放的皇后个数
- int q[MAXN];//利用q[MAXN]来记录执行的列数
- void dispasoulution(int n)//输出一个解
- {
- static int count=0;//定义静态变量来统计解的个数
- int i;
- printf("第%d个解:",++count);//每输出一次执行一次++
- for(i=1;i<=n;i++)
- printf("(%d,%d)",i,q[i]);//利用for循环依次输出解
- printf("\n");
- }
- int place(int k)//调用place函数判断能否放置该皇后
- {
- int i=1;
- while(i<k)
- {
- if((q[i]==q[k])||(abs(q[i]-q[k])==abs(i-k)))//判断是否满足约束关系,不能同列,不能同对角线
- return 0;
- i++;
- }
- return 1;
- }
- void queens(int n)
- {
- int k=1;//表示皇后个数或行数
- q[k]=0;//表示当前列,从开头存放
- while(1)
- {
- q[k]=q[k]+1;//测试下一列
- while(q[k]<=n&&!place(k))
- q[k]=q[k]+1;
- if(q[k]<=n)//找到第k个皇后的合适位置
- {
- if(k==n)//(皇后全部放置)
- dispasoulution(n);//当满足k==n时,输出这个解
- else
- {
- k++;//向下一行放置皇后
- q[k]=0;//从第一列开始
- }
- }
- else//如果没有找到合适的存放皇后的位置
- {
- if(k==1) exit(0);//如果回溯完成,算法结束
- k--;//回溯到上一行
- }
- }
-
- }
- void again()
- {
- int n;
- printf("请重新输入一个合适的N值:\n");
- scanf("%d",&n);
- if(n==1&&n>=4||n<=20)
- queens(n);
- else
- printf("禁止再次输入\n");
- }
- int main()
- {
- int n;
- printf("n皇后问题(n<20)\nn=");
- scanf("%d",&n);
- if(n>1&&n<4||n>20)
- {
- printf("n值不满足情况!\n");
- again();
- }
- else
- {
- printf("n皇后的问题求解如下:\n");
- queens(n);
- }
- }
复制代码 |