九度OJ-1459:Prime ring problem

2024-08-23 02:48
文章标签 problem prime oj ring 九度 1459

本文主要是介绍九度OJ-1459:Prime ring problem,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   本题从理论上可以转化为对状态的搜索,用枚举法暴力求解。但是其状态参量有N个,若转化为状态搜索则其判断状态检索过与否的mark数组将有N维,从实际上来说难以实现,故应另辟蹊径。

  这是一道典型的深度优先搜索(遍历解答树)!!

Debug记录:

①第一次遇到真的因为cout而TLE的情况。由于此题当n=16时会出现爆炸性的输出,故cout比printf多出来的时间消耗已经不容忽视。将cout改为printf后AC。

②OJ上不知道是哪个版本的编译器,总之<iostream>不带有c的scanf、printf等诸多基础输入输出函数,需要#include <cstdio>

③以后使用递归函数时候记得尽量统一出口,这样显得逻辑清晰。例如写此题时,先前没有统一DFS的返回出口,导致只在 “if (d.size()==n){ ”处(即满队情况的分支处)写了出口,而没在非满队的分支处写出口。本来非满队的分支处是不需要写出口的,但是由于我把退栈操作(退回上层前的回溯)统一写在了本层return之前,导致当此次DFS在非满队分支执行并且执行完毕返回上层时,没有了退栈回溯操作,导致出错。

收获如下:

①掌握了双端队列#include <deque>的用法(写法基本与<vector>一致),具体见STL容器专题。

②掌握了此类题目的做法:转化为对解答树的先序遍历(深度优先搜索),而非使用循环。因为若使用循环共需嵌套N层,从实际上来说实在难以实现。

③掌握了回溯法。回溯法(结束此层DFS时退栈)在此类对解空间的先序遍历(深度优先搜索)中经常使用,更是用来求解树的路径序列问题的必要方法。这个回溯操作放在统一 返回出口处写(自己的写法)是逻辑清晰的,不要像《指南》里头那样写,东一个西一个很不清晰很容易出bug。


题目描述:

A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.


输入:

n (1 < n < 17).

输出:

The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.

样例输入:
6
8
样例输出:
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2
提示:

用printf打印输出。



#include <iostream> 
#include <cstdio>
#include <cmath>
#include <deque>//由于回溯操作要用到删除队尾元素,故使用双端队列 
#define MAXSIZE 17
using namespace std;
deque<int> d;
bool prime[MAXSIZE*2+1];
bool mark[MAXSIZE+1];
int n;
void DFS(){if (d.size()==n){//当凑齐prime ring时 if (prime[d.back()+d.front()]==true){//若首尾满足条件,即已完成一个prime ring =>print 	deque<int> e=d;//声明临时队列e bool firstCase=true;while (!e.empty()){if (firstCase==true)firstCase=false;elseprintf(" ");printf("%d",e.front());e.pop_front();}printf("\n");}else{//不做任何事 }}else{for (int i=2;i<=n;i++){//add a number if (mark[i]==false&&prime[i+d.back()]==true){//若i还未放入q且满足i与前项和为素数 d.push_back(i);mark[i]=true;DFS();//继续添加 //下层已自动回溯 }}}//统一出口: //无论成功或者失败,都在此返回上层,并且返回前都要回溯 mark[d.back()]=false;d.pop_back();return;
}
int main(){//initiateint primeBound=2;prime[0]=prime[1]=false;prime[2]=true;bool isPrime=true;int time=1;//preprocessfor (int i=3;i<MAXSIZE*2+1;i++){//判断i是否为素数 isPrime=true;//initiate isPrimefor (int j=2;j<=primeBound&&j<sqrt(i)+1;j++){//遍历素数组来尝试整除 if (prime[j]==true){if (i%j==0){//能整除isPrime=false;break;} }}prime[i]=isPrime;if (isPrime){primeBound=i;}}//bodywhile (cin>>n){//initiate while (!d.empty())d.pop_front();for (int i=0;i<=n;i++){mark[i]=false;}d.push_back(1);mark[1]=true;//searchcout<<"Case "<<time<<":"<<endl;DFS();printf("\n");time++; }return true;
}


这篇关于九度OJ-1459:Prime ring problem的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1098135

相关文章

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

uva 10025 The ? 1 ? 2 ? ... ? n = k problem(数学)

题意是    ?  1  ?  2  ?  ...  ?  n = k 式子中给k,? 处可以填 + 也可以填 - ,问最小满足条件的n。 e.g k = 12  - 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12 with n = 7。 先给证明,令 S(n) = 1 + 2 + 3 + 4 + 5 + .... + n 暴搜n,搜出当 S(n) >=

九度1077(最大序列和)

题目链接:点击打开链接 解题思路: 很经典的一道题。首先考虑一下细节问题,当序列都是0时,显然最后要输出0;当序列都是负数时,显然要输出最大的数。 细节处理完了,就可以回到正常轨道。我们开两个变量,分别保存当前的序列和与之前的最大值,我们更新当前序列和的条件是如果当前序列和是负数的时候,那我们必须更新,否则一定会使最后结果减小。更新过程中还要更新之前最大值即可。 完整代码:

哈理工OJ 2179(深搜)

组合 Time Limit: 1000 MSMemory Limit: 32768 K Total Submit: 7(5 users)Total Accepted: 6(5 users)Rating: Special Judge: No Description 给出一个正整数N,从集合{1,2,3..N} 中找出所有大小为k的子集, 并按照字典序从小到大输出。 Input 第一行是一个整

11991 - Easy Problem from Rujia Liu?

题意: 输入一串整型数列,再输入两个数k,v,输出第k个v的序号。不存在则输出0,如第一个样例 8 41 3 2 2 4 3 2 11 3 //第1个3,序号为2,输出22 4 //第2个4,不存在,输出03 2 //第3个2,序号为7,输出74 2 思路: struct num {

每日OJ_牛客_求和(递归深搜)

目录 牛客_求和(递归深搜) 解析代码 牛客_求和(递归深搜) 求和_好未来笔试题_牛客网 解析代码         递归中每次累加一个新的数,如果累加和大于等于目标,结束递归。此时如果累加和正好等于目标,则打印组合。向上回退搜索其它组合。此题本身就是一个搜索的过程,找到所有的组合。 #include <iostream>#include <cmath>#in

HDU 1016 Prime Ring Problem (深搜)

OJ题目 : click here ~~ 大概题意:n个数,形成一个环,使得相邻两个数的和为素数。以1开始,按字典序输出序列。 很简单的深搜。 AC_CODE int n;int visit[22];int num[22];int len;bool Is_prime(int x){for(int i = 2;i*i <= x;i++)if(x%i == 0) return

LVM 'Can’t open /dev/sdb1 exclusively. Mounted filesystem?' Problem

在将几块盘做LVM时,遇到一个之前都没遇到过的问题: root@ubuntu:~# pvcreate /dev/sdc1Can't open /dev/sdc1 exclusively. Mounted filesystem? 首先第一反应就是查看这个分区是否已经在使用了,但是没有。 查看硬盘的一些信息: root@ubuntu:~# cat /proc/partitionsmajo

OJ-0905

题目 示例1: 输入:10 10 56 34 99 1 87 8 99 3 255 6 99 5 255 4 99 7 255 2 99 9 255 213 4输出:99 示例2: 输入:10 10 255 34 0 1 255 8 0 3 255 6 0 5 255 4 0 7 255 2 0 9 255 213 5输出:255 import java.util.