当前位置:编程学习 > JAVA >>

ACM模拟题详解(3)——数论(续)

5、Prime Ring Problem
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.

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.

 

Sample Input68 Sample OutputCase 1:1 4 3 2 5 61 6 5 2 3 4 Case 2:1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2

翻译:n个数字(1,2,3...n)围成一个圈,要求相邻的两个数字之和是质数。题目要求根据给出的n,计算所有能够组成满足条件的圈的数字序列。

解题思路:

首先选择1,然后选择和1相加等于质数的数字,可能有很多种情况,例如(n=6的情况):

1+21+41+6然后针对每种情况,再选择与第二个数的和为质数的数字,得到下面的序列

1+2+31+2+51+4+31+6+5直到所有的数字都选择完,把所有的组合列出即可。计算的过程就是构造下面的树的过程。

\

 

 

从图中可以看出1-4-3-2-5-6 和 1-6-5-2-3-4是两个合法的解。

对于树的遍历可以采用深度优先,也可以采用广度优先,如果采用广度优先占用的内存比较大,所以解空间比较大的时候不宜采用。

下面是采用广度优先实现的(当n=18和n=20的时候内存不够用)

    /*     * Prime Ring Problem     */    public static void test4(int n){       int values[] = new int[n];       // 初始化       for(int i=0;i<n;i++){           values[i] = i+1;       }              // 表示遍历过程中可能的解       List list = new ArrayList();       list.add(values);              // 处理后面的n-1个数字,1永远是第一个       for(int i=1;i<n;i++){           List temp = list;           list = new ArrayList();           // 对于每个可能的解,得到下一层节点           for(int j=0;j<temp.size();j++){              int tempValues[]=(int[])temp.get(j);              // 考虑所有可能的组合              for(int k=i;k<n;k++){                  if(isPrime(tempValues[i-1]+tempValues[k])){                     // 创建新的状态,并复制原来的值                     int[] newValues = Arrays.copyOf(tempValues, tempValues.length);                     // 交换i和k处的值                     if(i!=k){                         int change = newValues[i];                         newValues[i] = newValues[k];                         newValues[k] = change;                     }                     // 把新状态添加到列表中                     list.add(newValues);                  }              }           }       }       // 输出结果       for(int i=0;i<list.size();i++){           int[] tempValues = (int[])list.get(i);           if(isPrime(tempValues[0]+tempValues[n-1])){              for(int j=0;j<n;j++){                  System.out.print(tempValues[j]+" ");              }              System.out.println();           }       }       System.out.println(list.size());    }下面是深度优先的算法。

    /*     * Prime Ring Problem(深度优先)     */    public static void test5(int n){       // 数组的前n个元素表示环中的数字,第n+1个数据表示数组中前n+1个元素是满足条件的       int values[] = new int[n+1];       // 初始化       for(int i=0;i<n;i++){           values[i] = i+1;       }       values[n]=1;              // 表示遍历过程中可能的解       List list = new ArrayList();       list.add(values);       StringBuffer sb = new StringBuffer();       while(list.size()>0){           // 取出第一个元素           int tempValues[]=(int[])list.get(0);           // 表示处理到第几层,第一层用0表示           int index=tempValues[n];           // 遍历并生成所有可能的下一层节点           for(int k=tempValues[n];k<n;k++){              if(i

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,