488-素数环
- 内存限制:64MB 时间限制:1000ms 特判: No
题目描述:
有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。
为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。
输入描述:
有多组测试数据,每组输入一个n(0<n<20),n=0表示输入结束。输出描述:
每组第一行输出对应的Case序号,从1开始。 如果存在满足题意叙述的素数环,从小到大输出。 否则输出No Answer。样例输入:
复制
6 8 3 0样例输出:
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 Case 3: No Answer提示:
没有提示哦
来源:
上传者:ACM_丁国强
思路:
- DFS+回溯+剪枝
- 如果n是奇数直接输出No Answer,因为如果n是奇数的话,会多出一个奇数,奇数+奇数是偶数一定不会是素数,所以直接剪枝,但如果n是偶数的话不一定
AcCode:
import java.util.Scanner; public class Main { public static int[] primes = new int [51]; static { //埃式筛 primes[0] = 1; primes[1] = 1; for (int i = 2; i < primes.length; i++) { if(primes[i]==0) { int j = 2; for (; j*i < primes.length; j++) { primes[j*i] = 1; } } } } public static void main(String[] args) { Scanner in = new Scanner(System.in); int caseNum = 1; while(true) { int n = in.nextInt(); //count = 0; if(n==0) { break; } System.out.println("Case "+caseNum+":"); caseNum++; if(n==1) { System.out.println("1"); continue; } if((n&1)==1) { System.out.println("No Answer"); continue; } int[] isUse = new int[n+1]; int[] res = new int[n]; isUse[1] = 1;//标记其已经使用过 res[0] = 1; dfs(isUse,1,res); } } //public static int count = 0; private static void dfs(int[] isUse, int index,int[] res) { if(index==res.length) { //count++; for (int i = 0; i < res.length-1; i++) { System.out.print(res[i]+" "); } System.out.println(res[res.length-1]); return; } for (int i = 2; i < isUse.length; i++) { if(isUse[i]==1)continue; if(check(res,index,i)) {//检查相邻两个数是否是素数, 提前剪枝 isUse[i] = 1; res[index] = i; dfs(isUse, index+1, res); //回溯 isUse[i] = 0; res[index] = 0; } } } private static boolean check(int[] res, int index, int i) { if(index==res.length-1) { if(primes[res[index-1]+i]==0 && primes[1+i]==0) { return true; } }else { if(primes[res[index-1]+i]==0) { return true; } } return false; } }