搜索入门练习题1 素数环 题解

题目出处:《信息学奥赛一本通》例5.1。

题目描述

素数环:从 \(1\) 到 \(n(2 \le n \le 20)\) 这 \(n\) 个数摆成一个环,要求相邻的两个数的和是一个素数。

输入格式

输入包含一个整数 \(n(2 \le n \le 20)\) 。

输出格式

按字典序从小到大的顺序输出所有排列方案,每个排列方案占一行。每行的 \(n\) 个数之间由一个空格分隔。

样例输入

2

样例输出

1 2
2 1

问题分析

很明显,这是一道可以用搜索解决的问题,我们可以采用“回溯”思想,使用深度优先搜索解决这个问题。
我们用 ans[] 数组来存放我们当前遍历到的答案, ans[id] 用于表示当前排列的第 id 个数是什么。所以我们可以开一个函数 void f(int id) 来表示要在第 id 个位置放数,我只需要从 1 到 n 遍历每一个数(我这里假设是 i),并判断 i 是否能放。
在第 id 个位置能放 i 当且仅当:

  • \(ans[1]\) 到 \(ans[id-1]\) 都不等于 \(i\),即 \(i\) 之前没有放过;
  • 当 \(id \gt 1\) 时,满足 \(ans[id-1]+ans[id]\) 是素数;
  • 当 \(id = n\) 时,满足 \(ans[1] + ans[n]\) 是素数。

这样,我们递归地调用 f(id) ,当 id>n 时就是我们递归的边界条件;一旦 id>n 就说明我找到了一种方案。
实现代码如下:

#include<bits/stdc++.h>
using namespace std;
int ans[22], n;
bool isp(int a) {   // 判断a是否是素数
    if (a < 2) return false;
    for (int i = 2; i * i <= a; i ++) if (a%i==0) return false;
    return true;
}
void output() {     // 输出一种排列方案
    for (int i = 1; i <= n; i ++)
        cout << (i>1 ? " " : "") << ans[i];
    cout << endl;
}
void f(int id) {    // 搜索函数,在第id个位置尝试放上一个数
    if (id > n) {   // 边界条件
        if (isp(ans[1]+ans[n])) output();
        return;
    }
    for (int i = 1; i <= n; i ++) { // 遍历i = 1 to n ,看看第id个位置能否放i
        bool flag = true;
        if (id > 1 && !isp(ans[id-1]+i)) flag = false;
        if (flag) {
            for (int j = 1; j < id; j ++)
                if (ans[j] == i) {
                    flag = false;
                    break;
                }
        }
        if (flag) {
            ans[id] = i;
            f(id+1);
        }
    }
}
int main() {
    cin >> n;
    f(1);
    return 0;
}

原文地址:https://www.cnblogs.com/zifeiynoip/p/11450697.html

时间: 2024-07-29 14:19:51

搜索入门练习题1 素数环 题解的相关文章

搜索入门练习题3 全组合 题解

题目出处:<信息学奥赛一本通>例5.2. 题目描述 设有 \(n\) 个数的集合 \(\{1,2,...,n\}\) ,从中任意取出 \(r\) 个数进行排列 \((r \le n)\) ,试列出所有的排列. 输入格式 输入包含两个正数 \(n,r(1 \le r \le n \le 10)\) 输出格式 输出从 \(n\) 个数的集合中选出 \(r\) 个数的所有组合,每个组合方案占一行.对于每个组合,按照从小到大的顺序输出组合中的所有元素,两两之间有一个空格分隔. 样例输入 3 2 样例输

搜索入门练习题2 全排列 题解

题目出处:课程=>搜索1=>题目A 题目描述 给定一个正整数 \(n\) ,按照递增顺序打印数字 \(1\) 到 \(n\) 的所有排列. 输入格式 一个整数 \(n(1 \le n \le 7)\) . 输出格式 按照递增顺序输出 \(n\) 个数的所有排列,每行代表一组排列, \(n\) 个数两两之间有一个空格分隔. 样例输入 3 样例输出 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 问题分析 这是一道搜索的题目. 我们知道搜索就是状态到状态之间的转换,其本质是

搜索入门练习题4 数的拆分 题解

题目描述 任何一个大于 \(1\) 的自然数 \(n\) ,总可以拆分成若干个小于 \(n\) 的自然数之和.当 \(n = 4\) 时,总共有 \(4\) 种拆分方法: \(4=1+1+1+1\) \(4=1+1+2\) \(4=1+3\) \(4=2+2\) 现在给你一个数 \(n(1 \le n \le 20)\) ,请按顺序输出 \(n\) 的所有拆分方案. 输入格式 输入包含一个整数 \(n(1 \le n \le 20)\) . 输出格式 输出 \(n\) 的所有拆分方案,每种方案占

搜索入门练习题5 八皇后问题 题解

题目来源:<信息学奥赛一本通>例5.4 题目描述 要在国际象棋棋盘(\(8 \times 8\) 的棋盘)中放 \(8\) 个皇后,使任意两个皇后都不能互相吃.(提示:皇后能吃同一行.同一列.同一对角线的任意棋子.) 输出格式 输出一个整数,用于表示八皇后问题的放置方案. 题目分析 首先我们用 \((x,y)\) 来表示棋盘上第 \(x\) 行第 \(y\) 列的格子的坐标. 那么,两个皇后 \((x_1,y_1)\) 和 \((x_2,y_2)\) 会互相攻击当且仅当满足如下条件之一: 在同

搜索入门练习题7 最高效益和 题解

题目出处:<信息学奥赛一本通>例5.6 题目描述 设有A.B.C.D.E五人从事J1.J2.J3.J4.J5五项工作,每人只能从事一项,他们的效益如下所示. ? J1 J2 J3 J4 J5 A 13 11 10 4 7 B 13 10 10 8 5 C 5 9 7 7 4 D 15 12 10 11 5 E 10 11 8 8 4 每人选择五项工作中的一项,在各种选择的组合中,找到效益最高的一组输出. 题目分析 这道题目其实就是"全排列"问题的变形题,我们可以使用深度优先

素数环——搜索与回溯

题目描述 Description 从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数. 输入输出格式 Input/output 输入格式:无输入输出格式:一个整数(第几号素数环),一列数字(表示这个素数环) 输入输出样例 Sample input/output 样例测试点#1 输入样例: 无 输出样例: 这里就不演示了(…) 思路:代码很清楚,此处无需讲~~ 代码如下: 1 #include <stdio.h> 2 #include <math.h> 3 int a[3

深度搜索入门

深度优先搜索是搜索的手段之一.它从某个状态开始,不断地转移状态,直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此重复,直到找到最终的解. 做这类题目,抓住两样东西:1.总体上递归几次(几层)?每一次递归确定一层上的数. 2.每次递归,有几种选择的情况.所以dfs()函数,只有两部分(if.else结构):1.(if部分)若每一层都选择了,判断是否符合条件,做出题目要求的操作.2.(else部分)若还有层没有选择,就做出选择,所有选择的情况列出. 下面是几个考察dfs的题目: 1.部

HDU 1016 Prime Ring Problem(素数环问题)

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1016 Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 63806    Accepted Submission(s): 27457 Problem Description A ring is compos

素数环解题

<算法竞赛入门经典>这本书确实内容很丰富,但是对于初学者真的不怎么友善.主要的原因在于省略了太多的细节.为什么会有这样的情况呢?我个人是这样理解的,大多数人在给别人介绍一个知识点或者事物的时候,很容易将那些自己觉得比较简单或者基础的东西给省略掉.这种情况不是主观的,潜意识里就这么完成了.例如,我给一个人说,你看这瓶溶液是棕黄色的,至少不是硫酸铜.这里就有一个背景,硫酸铜溶液是蓝色的,我们为什么省略掉这个细节呢?因为我们潜意识里认为,别人也知道,而事实可能并非如此.回到这本书上来,有太多的内容也