算法设计与分析-回溯法思想的应用(头歌实验)

文章提供了两个版本的皇后问题解决方案,一个是非递归算法,另一个是递归算法,目标是在棋盘上放置皇后而不相互攻击。同时,第三部分介绍了如何将1到n的数字排列成环,使得相邻数字之和为素数。所有方法都涉及到了回溯和条件检查策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前两个都是用的递归,介意的可以自己写非递归,暴力即可。

第1关:非递归实现皇后问题

任务描述

本关任务:在n×n格的棋盘上放置彼此不受攻击的 n 个皇后。按照国际象的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。用非递归算法解决该问题。

下图是一个 8 个皇后的例子,8 个皇后彼此不受攻击。

编程要求

请在右侧编辑器Begin-End处补充代码,完成本关任务。

测试说明

平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:

测试输入:4(皇后的数目)

预期输出:

 
  1. * Q * *
  2. * * * Q
  3. Q * * *
  4. * * Q *
  5. * * Q *
  6. Q * * *
  7. * * * Q
  8. * Q * *
  9. 4皇后问题共有2种摆放方案

开始你的任务吧,祝你成功!

#include<stdio.h>
#include<stdlib.h>
#define bool char
#define true 1
#define false 0
#define  N 110
int n;
bool col[N];  //列
bool dg[N];  //正对角线
bool udg[N];  //反对角线
char g[N][N];
int solution;
void dfs(int u)
{
    if(u==n)    //搜索完毕
    {
        solution++;
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++){
                printf("  ");
                printf("%c",g[i][j]);
            }
            printf("\n") ; //按行输出,没输出一行会换行
        } 
        printf("\n") ;    //每输出一种答案换行
        
        return ;
    }
  
    for(int i=0;i<n;i++)    //u为行,i为列
    {
        if(!col[i]&&!dg[u+i]&&!udg[u-i+n])
        {
            g[u][i]='Q';
            col[i]=dg[u+i]=udg[u-i+n]=true;
            dfs(u+1);
            col[i]=dg[u+i]=udg[u-i+n]=false;  //回溯
            g[u][i]='*';     //回溯
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) 
        for(int j=0;j<n;j++)
            g[i][j]='*';     //初始化
    dfs(0);  
    printf("%d皇后问题共有%d种摆放方案",n,solution) ;
    return 0;
}

第2关:递归算法解决皇后问题

任务描述

本关任务:在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。用递归算法解决该问题。

编程要求

请在右侧编辑器Begin-End处补充代码,完成本关任务。

测试说明

平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:

测试输入:4(皇后的数目)

预期输出:

 
  1. * Q * *
  2. * * * Q
  3. Q * * *
  4. * * Q *
  5. * * Q *
  6. Q * * *
  7. * * * Q
  8. * Q * *
  9. 4皇后问题共有2种摆放方案

开始你的任务吧,祝你成功!

#include<stdio.h>
#include<stdlib.h>
#define bool char
#define true 1
#define false 0
#define  N 110
int n;
bool col[N];  //列
bool dg[N];  //正对角线
bool udg[N];  //反对角线
char g[N][N];
int solution;
void dfs(int u)
{
    if(u==n)    //搜索完毕
    {
        solution++;
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++){
                printf("  ");
                printf("%c",g[i][j]);
            }
            printf("\n") ; //按行输出,没输出一行会换行
        } 
        printf("\n") ;    //每输出一种答案换行
        
        return ;
    }
  
    for(int i=0;i<n;i++)    //u为行,i为列
    {
        if(!col[i]&&!dg[u+i]&&!udg[u-i+n])
        {
            g[u][i]='Q';
            col[i]=dg[u+i]=udg[u-i+n]=true;
            dfs(u+1);
            col[i]=dg[u+i]=udg[u-i+n]=false;  //回溯
            g[u][i]='*';     //回溯
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) 
        for(int j=0;j<n;j++)
            g[i][j]='*';     //初始化
    dfs(0);  
    printf("%d后问题共有%d种摆放方案",n,solution) ;
    return 0;
}

第3关:素数圈

任务描述

本关任务:把从 1 到 n 这 n 个数摆成一个环,要求相邻的两个数的和是一个素数。

编程要求

请在右侧编辑器Begin-End处补充代码,完成本关任务,输出格式请参考测试集。

测试说明

平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:

测试输入: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 <math.h>
#include <stdlib.h>
#include <stdbool.h>
#define N 100
int n,x[N];
bool vis[N],flag=false;
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;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值