您的位置:首页 > 其它

将1、2、...、20这20个数排成一排,使得相邻的两个数之和为一个素数,且首尾两数字之和也为一个素数。

2012-10-17 18:32 316 查看


将1、2、...、20这20个数排成一排,使得相邻的两个数之和为一个素数,且首尾两数字之和也为一个素数。

这里提供了三种方法:

(注意:为了让程序更快,根据排列的特点,每种方法都固定了最后一个元素,这样输出只是满足条件中的一部分,但是你可以修改每种方法中的输出,所有元素通过移动一个位置来输出, 如123,第一次输出123,第2次231,第3次312,这样就可以得到所有的解。)

下面只对其中的暴力方法做简单的说明。

暴力方法思想:对1-n做出所有的排列,然后依次检查每个排列看是否满足条件,满足的输出。

其中的递归只是做出排列。排列递归的思想就是,任选1到n中的一个放到最后位置,(递归)任选剩余的数中的一个放到次后位置,*** ,按照这样循环下去。

顺便提一下,这种方法很慢,做完所有排列要进行递归几十亿亿次,你要等很久(可能久到几个小时,哈哈)才能看到结果。 但是,你可以把我注释的for语句代替其下的for可以快一点看到结果。

具体看代码中的解释。

看懂暴力方法,就能看懂方法三了。一就不用看了,可能你也看不懂。虽然它的速度是这三个比较快的一个,但理解也更难。

如果这样你都看不懂,那么是你的问题了,可能你根本不知道什么是排列,也可能你根本不知道什么是递归,一切都是白说。(那样你应该找本书看,而不是光问。)

#include <stdio.h>

#include <malloc.h>

#include <memory.h>

#include <math.h>

#include <time.h>

bool IsPrimeNumber(int n)

{ /*判断素数*/

int i;

int sqrootN;

if ( n == 2 ) {

return true;

} else if ( n%2 == 0 || n==1 ) {

return false;

}

sqrootN = (int)( sqrt(n)+0.1 )+1;

i = 3;

while ( i < sqrootN ) {

if (n%i == 0) {

return false;

}

i += 2;

}

return true;

}

void Swap(int *a, int *b)

{ /*交换两数*/

int tmp;

tmp = *a;

*a = *b;

*b = tmp;

}

bool IsOk(int *arr, int arrsize)

{ /*判断是否满足条件*/

if ( !IsPrimeNumber(arr[arrsize-1]+arr[0]) ) {

return false;

}

while( --arrsize > 0 ) {

if ( !IsPrimeNumber(arr[arrsize]+arr[arrsize-1]) ) {

return false;

}

}

return true;

}

////////////////////////////////////////////////////////

// 方法一:

bool Adjust_Pair(int *arr, int arrsize, int depth)

{

static int total=0;

bool ret = false;

int i;

if ( depth==2 ) {

if ( IsPrimeNumber(arr[0]+arr[arrsize-1]) ) {

total++;

printf("\n%03d: ",total);

for( i=0; i<arrsize; i+=2 ) {

printf("%02d-%02d ", arr[i], arr[i+1]);

}

return true;

} else {

return false;

}

}

for (i=depth-2; i>1; i-=2) {

if ( IsPrimeNumber(arr[i-1]+arr[depth-2]) ) {

Swap(arr+depth-3, arr+i-1);

Swap(arr+depth-4, arr+i-2);

if ( Adjust_Pair(arr, arrsize, depth-2) ) {

ret = true;

}

Swap(arr+depth-3, arr+i-1);

Swap(arr+depth-4, arr+i-2);

}

}

return ret;

}

bool Make_Pair(int *arr, int arrsize, int depth)

{

bool ret = false;

int i;

static int total1=0;

static int total2=0;

if ( depth==0 ) {

return Adjust_Pair(arr, arrsize, arrsize);

}

for( i=0; i<depth-1; i+=2 ) {

if ( IsPrimeNumber(arr[depth-1]+arr[i]) ) {

Swap(arr+depth-2, arr+i);

if ( Make_Pair(arr, arrsize, depth-2) ) {

ret = true;

}

Swap(arr+depth-2, arr+i);

}

}

return ret;

}

void DoPermutation(int *arr, int arrsize)

{

if(arrsize%2==1) {

printf("\n结果:不存在(数组大小必须为偶数).");

return;

}

if ( !Make_Pair(arr, arrsize, arrsize) ) {

printf("\n结果:不存在.");

}

}

//////////////////////////////////////////////////////

//暴力方法:无条件进行所有排列,并逐一判断是否满足条件

bool _DoPermutation2(int *arr, int arrsize, int depth)

{

static int total=0;

bool ret = false;

int i;

if ( depth==0 ) { /*排列完成*/

if ( IsOk(arr, arrsize) ) { /*判断是否满足条件, 满足条件就输出*/

total++;

printf("\n%03d: ",total);

for( i=0; i<arrsize; i+=2 ) {

printf("%02d-%02d ", arr[i], arr[i+1]);

}

return true;

} else {

return false;

}

}

/* for ( i=(depth+1)%2; i<depth; i+=2 ) { 将下面for换成这个for可以优化一半的速度*/

for ( i=0; i<depth; i++ ) { /*depth-1相当于数组的最后一个位置*/

Swap(arr+depth-1, arr+i); /*选择arr[i]到放到数组的最后一个位置arr[depth-1]*/

if ( _DoPermutation2(arr, arrsize, depth-1) ) { /*递归排列前depth-1个元素*/

ret = true;

}

Swap(arr+depth-1, arr+i); /*交换回来,让原来的数组不变*/

}

return ret;

}

void DoPermutation2(int *arr, int arrsize)

{

if(arrsize%2==1) {

printf("\n结果:不存在(数组大小必须为偶数).");

return;

}

if ( !_DoPermutation2(arr, arrsize, arrsize-1) ) {

printf("\n结果:不存在.");

}

}

//////////////////////////////////////////////////////

// 方法三:当且仅当正在进行的排列满足部分条件时,进行递归

bool _DoPermutation3(int *arr, int arrsize, int depth)

{

static int total=0;

bool ret = false;

int i;

if ( depth==0 ) {

if ( IsPrimeNumber(arr[arrsize-1]+arr[0]) ) {

total++;

printf("\n%03d: ",total);

for( i=0; i<arrsize; i+=2 ) {

printf("%02d-%02d ", arr[i], arr[i+1]);

}

return true;

} else {

return false;

}

}

for ( i=(depth+1)%2; i<depth; i+=2 ) {

/* for ( i=0; i<depth; i++ ) { 将上面换成这句也可以,但上面更好*/

if ( !IsPrimeNumber(arr[depth]+arr[i]) ) {

continue;

}

Swap(arr+depth-1, arr+i);

if ( _DoPermutation3(arr, arrsize, depth-1) ) {

ret = true;

}

Swap(arr+depth-1, arr+i);

}

return ret;

}

void DoPermutation3(int *arr, int arrsize)

{

if(arrsize%2==1) {

printf("\n结果:不存在(数组大小必须为偶数).");

return;

}

if ( !_DoPermutation3(arr, arrsize, arrsize-1) ) {

printf("\n结果:不存在.");

}

}

int main(int argc, char* argv[])

{

clock_t start, finish;

int arr[100],i;

for( i=0; i<100; i++ ) {

arr[i]=i+1;

}

/*方法一*/

DoPermutation(arr, 18);

/*暴力方法*/

/*DoPermutation2(arr, 18);*/

/*方法三*/

/*DoPermutation3(arr, 18); */

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐