Problem Description
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.
Note: the number of first circle should always be 1.
Input
n (0 < n < 20).
Output
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.
You are to write a program that completes above process.
Print a blank line after each case.
Sample Input
6 8
Sample Output
Case 1: 1 4 3 2 5 6 1 6 5 2 3 4 Case 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
题意:输入一个n,将1到n中各个数排成一个圆,要求相邻的两个数之和为素数(起始的数为1)。
解题思路:因为起始为1,所以首先用1去和其他数相加判断是否为素数,若是,则继续让这个与下一个没有用过的数进行相加,以此类推,不难看出这是一个搜索题型。然后将此转化为代码即可。
方法一:步骤详细,思路清楚,就是有点绕,但是理解起来还是比较容易的(只是在杭电里不能ac而已,java超时超内存原因)。
package search;
import java.util.Scanner;
public class SearchMethodDFS1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int a[] = new int[n];//用来存储每个结点的值
int color[] = new int[n];//颜色,搜索标志。-1---未搜索,1为已搜索
int parent[] = new int[n];//用于记录每个元素的父结点
//初始化
for(int i=0;i<n;i++){
a[i] = i+1;//结点的值
color[i] = -1;
parent[i] = -1;
}
int startNode=0;//搜索起始结点的下标
int count=0;//相当于《算法导论》中的time,此处用于代表所搜的结点数,当结点数为n时则代表搜索完成
dfs(a,color,parent,startNode,count);
}
}
private static void dfs(int[] a, int[] color, int[] parent, int u, int count) {
color[u] = 1;
count++;
//System.out.println(a[u]);
//递归鸿沟
if(count==a.length && isPrime(a[u]+a[0]) ){
parent[0] = u;
print(a,parent);
return;
}
for(int v=0; v<a.length; v++){
if(color[v]==-1 && isPrime(a[u]+a[v]) ){
parent[v] = u;
/*法1
dfs(a,color,parent,v,count);
//※※还原现场
color[v] = -1;
parent[v] = -1;
*/
//法2 做数据备份,把备份数据传进递归搜索
int color2[] = new int[a.length];
int parent2[] = new int[a.length];
for(int i=0;i<a.length;i++){
color2[i] = color[i];
parent2[i] = parent[i];
}
dfs(a,color2,parent2,v,count);
}
}
}
<span style="white-space:pre"> </span>//输出最终结果
private static void print(int[] a, int[] parent) {
int index[] = new int[parent.length];
int p=0;
for(int i=0;i<parent.length;i++){//因为这种方法是记父节点形式记录结果的,所以结果需要倒序
index[parent.length-1-i] = parent[p];
p = parent[p];
}
for(int i=0;i<index.length;i++){
if(i<index.length-1){
System.out.print(a[index[i]]+" ");
}else{
System.out.println(a[index[i]]);
}
}
}
<span style="white-space:pre"> </span>//判断是否为素数
private static boolean isPrime(int n) {
if(n==2){
return true;
}
for(int i=2;i*i<=n;i++){
if(n%i==0){
return false;
}
}
return true;
}
}
方法二(可以在杭电ac):这个就是直接将解题思路直接翻译过来的,即:先是1,然后找到与1相邻的符合条件的数放在s[]中,以此类推,直到找到最后一个数。(也就是依次求出相邻的数)
import java.util.Scanner;
public class P1016 {
private static int[] s;
private static int[] visit;
private static int sign,n;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int k=1;
while(sc.hasNext()){
s=new int[20];
s[1]=1;
visit=new int[20];
visit[1]=1;
n=sc.nextInt();
System.out.println("Case "+k+":");
k++;
DFS(2);
System.out.println();
}
}
private static void DFS(int x) {
if(x>n&&isPriem(s[x-1]+1)){
print(s);
}
for(int i=2;i<=n;i++){
if(visit[i]==0&&isPriem(s[x-1]+i)){
s[x]=i;
visit[i]=1;
DFS(x+1);
visit[i]=0;
}
}
}
private static void print(int[] s2) {//输出结果
for(int i=1;i<n;i++){
System.out.print(s2[i]+" ");
}
System.out.println(s2[n]);
}
private static boolean isPriem(int x) {//判断是否为素数
if(x==2){
return true;
}
for(int i=2;i*i<=x;i++){
if(x%i==0){
return false;
}
}
return true;
}
}
方法三:面向对象方法
package search;
import java.util.Scanner;
public class SearchMethodDFS2 {
public static boolean isPrime(int n){
if(n==2)
return true;
for(int i=2;i*i<=n;i++){
if(n%i==0){
return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
//初始化图
Node nodes[] = new Node[n];
for(int i=0;i<nodes.length;i++){
nodes[i] = new Node(i+1,-1,null);
}
int startNum=0;
int count=0;//计数
dfs(nodes,startNum,count);
}
}
private static void dfs(Node[] nodes, int u, int count) {
count++;
nodes[u].color=1;
//鸿沟
if(count==nodes.length && isPrime(nodes[u].value+nodes[0].value) ){
print(nodes,u);
}
for(int v=1;v<nodes.length;v++){
if(nodes[v].color==-1 && isPrime(nodes[u].value+nodes[v].value)){
nodes[v].parent = nodes[u];
dfs(nodes,v,count);
nodes[v].color=-1;
nodes[v].parent=null;
}
}
}
private static void print(Node[] nodes, int u) {
Node nodes2[] = new Node[nodes.length];
Node node = nodes[u];
for(int i=nodes.length-1; i>=0; i--){
nodes2[i] = node;
node = node.parent;
}
int i=0;
for(;i<nodes.length-1;i++){
System.out.print(nodes2[i].value+" ");
}
System.out.println(nodes2[i].value);
}
}
class Node{
int value;
int color;
Node parent;
public Node(int value, int color, Node parent) {
this.value = value;
this.color = color;
this.parent = parent;
}
}