您的位置:首页 > 编程语言 > Java开发

HDU 1016(Java) 好大一个坑!!!

2016-03-02 19:09 441 查看
Prime Ring Problem

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 38463 Accepted Submission(s): 17008

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 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

深搜的一道水题,原先用C++AC了,因为要学习Java,就用Java撸了一遍。然而悲剧就这么发生了,同样的逻辑代码,符号题目要求的输出,提交了一整天总是presentation error,万般无奈之下去网上搜AC代码,然而没有Java版的,所以只好对着C语言一个个看,后来一步一步调试,才发现要在Case %d:后面再加个空格(可是题目描述和C++版中都没有这个空格)。~~~~,虽然Java运行慢,用Java打比赛的人少,但也不能这么坑人吧!

import java.util.Arrays;
import java.util.Scanner;

public class Main {
public static int kase = 0,n;
public static int[] circles = new int[50];
public static boolean[] flag = new boolean[50],primes = new boolean[50];
static boolean DEBUG = false;
static void debug(){
System.out.print("***");
}
public static void initPrimes(){
Arrays.fill(primes, true);
for(int i=2;i<=30;i++){
for(int j=i+i;j<50;j+=i){
if(j%i==0) primes[j] = false;
}
}
primes[0]=primes[1] = false;
}
public static void DFS(int i){
if(i==n){
if(primes[1+circles[n-1]]){
for(int j=0;j<n;j++){
if(j==n-1) System.out.print(circles[j]);
else System.out.print(circles[j]+" ");
}
System.out.println();
}
return ;
}
else{
for(int j=2;j<=n;j++){
if(flag[j]){
if(primes[j+circles[i-1]]&&((j+circles[i-1])&1)!=0){//相邻的数奇偶性不同,剪枝!
flag[j] = false;
circles[i] = j;
DFS(i+1);
flag[j] = true;
}
}
}
}
return ;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
initPrimes();
while(in.hasNext()){
n = in.nextInt();
//就是这个坑!!
System.out.printf("Case %d: \n", ++kase);
if(n==1){
System.out.println(1);
System.out.println();
continue;
}
else if((n&1)!=0){
System.out.println();
continue;
}
Arrays.fill(flag, true);
circles[0] = 1;
flag[1] = false;
DFS(1);
System.out.println();
//  if(DEBUG) debug();
}
}

}


note:

1.数据规模小,所以把1~37的所有素数都找到了,打表空间换时间。

2.数据优化:再考虑输入的特点,如果输入N是奇数的话,由于起点从1开始,那么1-N之间一共有N / 2个偶数,N / 2 + 1个奇数,也就是奇数的个数比偶数多一个,那么把这N个数排成一个环,根据鸽巢原理,必然有两个奇数是相邻的,而两个奇数之和是偶数,偶数不是素数,所以我们得出结论,如果输入N是奇数的话,没有满足条件的排列。这样当N是奇数的时候,直接返回即可。如果1-N之间每个数输入的几率相同,这个判断可以减少一半的计算量。

3.剪枝:两个奇数之和或者两个偶数之和都是偶数,而偶数一定不是素数,所以在选取当前元素的时候,比较一下它和前一个元素的奇偶性。再做决定,可以减少一部分计算量。

4.位运算按位于判断整数N奇偶性:由于奇数的二进制表示中,最低位是1,N与1按位与运算(N&1)后结果是1,则说明N是一个奇数,否则是一个偶数。即输出结果环中相邻的数奇偶性一定不相同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: