转载声明:原文转自http://www.cnblogs.com/xiezie/p/5576273.html

题意:

一个环是用图中所示的n个圆组成的。把自然数1、2、……、n分别放入每个圆中,并在相邻的圆中的数值总和为一个质数。
注:第一圈数应该是1。

输出:

输出格式显示为下面的示例。每一行代表在环里圆中的数从1开始顺时针和逆时针。数字的数量必须满足上述要求。按字典顺序打印解决方案。
你是写一个程序,完成上述过程。
每一种情况下打印一条空白线。

题目分析:

首先,因为需要遍历多次,质数不可能每次判断的时候都重新计算,应该生产质数表(0<n<20,因此质数表中的质数小于40)。

java算法如下:

    /*
* 输入数字,作为序号传入
* 判断是否质数
* */
static boolean isAPrimeInForty(int num){
if(isPrimes[num]==1){
return true;
}
return false;
} /*
* 生产序号为0-39的0,1序列
* 1代表为质数
* 0代表为非质数
* */
static int[] isPrimes = createPrimes(); static int[] createPrimes(){
int[] primes = new int[40];
for(int i = 2 ; i != 40 ; i ++ ){
if(isAPrime(i)){
primes[i] = 1;
}
}
return primes;
} //判断是否质数
static boolean isAPrime(int num){
int len = (int) (Math.sqrt(num)+1);
for(int i = 2 ; i != len ; i ++){
if(num%i==0){
return false;
}
}
return true;
}

解题:

第一次,由于最近搞了全排列,我的解题思路是:将所有数进行字典序全排列(由于数字是顺序输入数组,我在字典序排列中省去了排序的过程),并判断是否符合题中条件。如果是则存储(因此,顺时针逆时针都包括)或者直接输出。

结果:Time Limit Exceeded----------不过我相信这样做答案一定是正确的

代码如下:

import java.util.*;

import java.io.*;

public class Main{

    public static void main(String[] arg){
Scanner scan = new Scanner(new BufferedInputStream(System.in));
int n;
int count = 1;
while(scan.hasNextInt()){
n = scan.nextInt();
System.out.println("Case "+ count+++ ":" );
int[] nums = new int[n];
for(int i = 0 ; i != n; i ++){
nums[i] = i+1;
}
getAllPermutationsAndCheck(nums,1,n-1);
System.out.println();
}
scan.close();
} static boolean isAnswer(int[] nums){//判断数组是否符合条件
int len = nums.length;
for(int i = 0 ; i != len ; i ++ ){
int sum = nums[i%len] + nums[(i+1)%len];
if(!isAPrimeInForty(sum)){
return false;
}
}
return true;
} static boolean isAPrime(int num){//判断是否质数
int len = (int) (Math.sqrt(num)+1);
for(int i = 2 ; i != len ; i ++){
if(num%i==0){
return false;
}
}
return true;
} static void getAllPermutationsAndCheck(int[] cs,int start,int len){//cs为字典序数组
if(cs==null)
return;
while(true)
{
if(isAnswer(cs)){
for(int j = 0 ; j != cs.length; j ++){
if( j == cs.length -1){
System.out.print(cs[j]);
break;
}
System.out.print(cs[j] + " ");
}
System.out.println();
}
int j=start+len-2,k=start+len-1;
while(j>=start && cs[j]>cs[j+1])
--j;
if(j<start)
break; while(cs[k]<cs[j])
--k; swap(cs,k,j); int a,b;
for(a=j+1,b=start+len-1;a<b;++a,--b)
{
swap(cs,a,b);
}
}
} static boolean isAPrimeInForty(int num){//判断是否质数
for(int i = 0 ; i != 12 ; i ++ ){
if(num>primes[i]){
continue;
}
if(num==primes[i]){
return true;
}
if(num<primes[i]){
return false;
}
}
return false;
} static int[] primes = createPrimes(); static int[] createPrimes(){
int[] primes = new int[12];
int count = 0;
for(int i = 2 ; i != 40 ; i ++ ){
if(isAPrime(i)){
primes[count] = i;
count++;
}
}
return primes;
} static void swap(int[] nums , int i , int j){
int t;
t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}

当然,当我全排列10个数的时候,秒输出,当我全排列12个数的时候,半天都输出不了~

只能说明:全排列是最差的暴力破解,没有进行剪枝

下面一个思路是:深度搜索

  同样是字典序全排列(不过是从1-n的全排列,有了具体场景)

  但是在字典序全排列过程中,进行剪枝,遇到一个前后相加不为质数的就跳过(省去了后面的全排列)

结果:Accepted    执行占用时间:2698MS   执行占用内存:13940K

具体java算法如下:

import java.util.*;

import java.io.*;

public class Main{

    public static void main(String[] arg){
Scanner scan = new Scanner(new BufferedInputStream(System.in));
int n;
int count = 1;
answer[0] = 1;
while(scan.hasNextInt()){
n = scan.nextInt();
System.out.println("Case "+ count+++ ":" );
checkAndOutput(n,1);
System.out.println();
}
scan.close();
} static int[] answer = new int[21];
static int[] isUsed = new int[21]; static void checkAndOutput(int n,int index) {//index为数组的序号
int len = n+1;
int last = n-1;
if(index == n){
for(int i=0; i != n ; i ++ ){
if(i == last){
System.out.println(answer[i]);
return;
}
System.out.print(answer[i]+" ");
}
}
for(int i = 2 ; i != len ; i ++ ){//数组序号为index的遍历
if(isUsed[i] == 0){
if(!isAPrimeInForty(i + answer[index-1])){
continue;
}
isUsed[i]=1;
answer[index] = i;
if(index==last){
if(!isAPrimeInForty(1+ answer[index])){//增加一步头尾相加判断
isUsed[i]=0;
continue;
}
}
checkAndOutput(n,index+1);
isUsed[i]=0;
}
}
} /*
* 输入数字,作为序号传入
* 判断是否质数
* */
static boolean isAPrimeInForty(int num){
if(isPrimes[num]==1){
return true;
}
return false;
} /*
* 生产序号为0-39的0,1序列
* 1代表为质数
* 0代表为非质数
* */
static int[] isPrimes = createPrimes(); static int[] createPrimes(){
int[] primes = new int[40];
for(int i = 2 ; i != 40 ; i ++ ){
if(isAPrime(i)){
primes[i] = 1;
}
}
return primes;
} //判断是否质数
static boolean isAPrime(int num){
int len = (int) (Math.sqrt(num)+1);
for(int i = 2 ; i != len ; i ++){
if(num%i==0){
return false;
}
}
return true;
} static void swap(int[] nums , int i , int j){
int t;
t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}

HDOJ-ACM1016(JAVA) 字典序全排列,并剪枝的更多相关文章

  1. java字典序全排列

    import java.util.Arrays; /** *字典序全排列 *字符串的全排列 *比如单词"too" 它的全排列是"oot","oto&q ...

  2. 字典序全排列(java实现)

    import java.util.Arrays; /** *字典序全排列 *字符串的全排列 *比如单词"too" 它的全排列是"oot","oto&q ...

  3. 面试:如何找出字符串的字典序全排列的第N种

    1.题目 如何找出字符串的字典序全排列的第N种?(字符串全排列的变种) 2.思路 主要想通过这题,介绍一下康托展开式.基于康托展开式可以解决这个问题. 一般的解法:①求出所有全排列 ②按照字典序排个序 ...

  4. java实现全排列输出

    java实现全排列输出 转自:http://easonfans.iteye.com/blog/517286 最近在找工作,面试java程序员或者软件工程师,在笔试的时候常常见到这么一道题:全排列 的输 ...

  5. java实现全排列

    前天上午的面试遇到了一个用java实现一串数字的全排列的题,想来想去用递归最方便,可是没有在规定的时间内完成555,今天上午有空便继续写,以下是完成后的代码: import java.util.Arr ...

  6. java实现全排列问题

    1.问题描述: 一组字符串的全排列,按照全排列的顺序输出,并且每行结尾无空格. 2.输入: 输入一个字符串 3.输入示例: 请输入全排列的字符串: abc 4.输出示例: a b c a c b b ...

  7. JAVA求解全排列

    一,问题描述 给定一个字符串,求出该字符串的全排列. 比如:"abc"的全排列是:abc.acb.bac.bca.cab.cba 二,实现思路 采用递归的方式求解.每次先选定一个字 ...

  8. hdoj 5113 Black And White DFS+剪枝

    Black And White Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others) T ...

  9. java字典序排序

    import java.util.Comparator; import java.util.ArrayList; import java.util.Collections; public class ...

随机推荐

  1. 在jsp中运用ajax实现同一界面不跳转处理事件

    目前,编写应用程序时有两种基本的选择: 桌面应用程序 Web应用程序 它们有什么区别呢?桌面应用程序一般很快(就在您的计算机上运行,不用等待互联网连接),具有漂亮的用户界面(通常和操作系统有关)和非凡 ...

  2. Codeforces 612E - Square Root of Permutation

    E. Square Root of Permutation A permutation of length n is an array containing each integer from 1 t ...

  3. IBatis.net在asp.net MVC下的使用

    IBatis.net 是2001年发起的开源项目,它是一个轻量级的ORM框架,现在IBatisNET已经是属于Apache下的一个子项目了,最新版本是1.6.2. 官方网站:http://www.my ...

  4. I2C总线模拟(郭天祥视屏)

    电路图 思路 1.向EEPROM中通过I2C总线写入一个字节 2.通过I2C总线读出写入的字节 3.如果写入和读出成功点亮发光二极管 程序 #include <REGX51.H> #def ...

  5. 找工作ing

    找工作已经一个月多了,这一个月跑来跑去,挺累的,倒也不是身体有多累,关键是心累!作为一名控制工程专业的研究生,想找一份软件开发类的工作,没想到这么难!在起初的时候,觉得自己C++和JAVA都会,找哪个 ...

  6. 性能测试_响应时间、并发、RPS的关系

    写这篇文章是为了帮自己理清一下性能测试中最最基本,却总是被人忽略的一些概念. 并发: 什么叫并发?并发不是我们理解的在loadrunner场景中设置并发数,而是正在系统中执行操作或者在系统的队列中排队 ...

  7. Linux配置系统

    配置架构: 三元素: 配置文件, 环境变量, 命令行选项 三级别: 系统级,用户级,程序级 应用: 调用时可能发生变化的配置信息,使用命令行选项:改动很少但确实应该由各个用户自己控制的配置信息,使用用 ...

  8. ANDROID_MARS学习笔记_S01原始版_009_SQLite

    一.代码1.xml(1)activity_main.xml <?xml version="1.0" encoding="utf-8"?> <L ...

  9. 学习笔记-[Maven实战]-第一章:Maven简介

    Maven简介: Maven 可翻译为:知识的积累,也可以翻译为"专家"或"内行". Maven 是一个跨平台的项目管理工具,是Apache组织中一个很成功的开 ...

  10. Sublime Text修改显示图标

    选择喜欢的图片 首先你需要选择一个中意的图片做为新的图标,格式可以是png,jpg,gif的 转为ico格式 我们需要ico格式的图片,所以需要将上述的图片转换一下格式.同样,转ico格式的软件很多, ...