第1关:非递归实现皇后问题
任务描述
本关任务:在
n×n
格的棋盘上放置彼此不受攻击的 n 个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。用非递归算法解决该问题。测试输入:
4
(皇后的数目)预期输出:
* Q * *
* * * Q
Q * * *
* * Q *
* * Q *
Q * * *
* * * Q
* Q * *
4皇后问题共有2种摆放方案
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX 100
int n,x[MAX],sum;
bool check(int k)//约束剪枝
{
for(int j=1;j<k;j++)
{
if(abs(j-k)==abs(x[j]-x[k])||x[j]==x[k]) //同斜线和同列
return false;
}
return true;
}
void output()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j==x[i])
printf(" Q");//样例*和Q之间的间隔是两个空格
else
printf(" *");
}
printf("\n");
}
sum++;
printf("\n");
}
int main()
{
scanf("%d",&n);
int t=1;
while(t>0)
{
x[t]+=1;
while(x[t]<=n&&!check(t))
x[t]+=1;//确定序列,即第t行放置的数,如果check为false说明冲突,需要+1到下一个数,以此类推
if(x[t]<=n)//说明此时check为true,合法位置
{
if(t==n)//到达边界(叶节点),输出结果
output();
else
{
t++;//未到达叶节点,继续往下搜索,到下一行
x[t]=0;
}
}
else
t--;//到达叶节点后仍找不到合法位置,回溯到上一层
}
printf("%d皇后问题共有%d种摆放方案",n,sum);
return 0;
}
第2关:递归算法解决皇后问题
任务描述
本关任务:在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。用递归算法解决该问题。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX 100
int sum=0,n;
int x[MAX];
bool vis[MAX];
bool check(int i)
{
for(int j=1;j<i;j++)
{
if(abs(j-i)==abs(x[i]-x[j]))
return false;
}
return true;
}
void output()
{
sum++;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j==x[i])
printf(" Q");
else
printf(" *");
}
printf("\n");
}
printf("\n");
}
void dfs(int i)
{
if(i>n)
output();
else
{
for(int j=1;j<=n;j++)
{
if(!vis[j])
{
vis[j]=true;
x[i]=j;
if(check(i))
dfs(i+1);
vis[j]=false;
}
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
printf("%d后问题共有%d种摆放方案",n,sum);
return 0;
}
/********** End **********/
第3关:素数圈
任务描述
本关任务:把从 1 到 n 这 n 个数摆成一个环,要求相邻的两个数的和是一个素数。
测试输入:
20
预期输出:
围成的圈是:1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 20 11 12 19 18
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define MAX 100
int n,x[MAX];
bool vis[MAX],flag=false;
/********** Begin **********/
bool checkPrime(int t)//约束条件 相邻的和为素数
{
for(int j=2;j<=sqrt(t);j++)
{
if(t%j==0)
return false;
}
return true;
}
void dfs(int i)
{
if(i>n)
{
if(flag){
printf("围成的圈是:");
for(int j=1;j<i;j++)
printf("%d ",x[j]);
exit(0);
}
flag=true;//我观察样例发现我的第二个才和它一样 我也不知道为啥 有知道的朋友欢迎交流哇
}
else
{
for(int j=1;j<=n;j++)
{
if(!vis[j]&&checkPrime(x[i-1]+j))
{
vis[j]=true;
x[i]=j;
dfs(i+1);
vis[j]=false;
}
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
return 0;
}
/********** End **********/