读书人

将1,2,3,4…20这20个自然数排成一个圈

发布时间: 2012-03-29 12:53:13 作者: rapoo

将1,2,3,4……20这20个自然数排成一个圈,使任意两个相邻的自热数之和均为素数。
[code=C/C++][/code]

希望读者可以耐心看完我的代码。
#include <stdio.h>
#include <math.h>
bool sushu(int m)//判断是否是素数
{
int i;
for(i = 2; i <= sqrt(m) ; i ++)
{
if(m % i == 0)
break;
else
continue;
}
if(i > sqrt(m))
return true;
else
return false;
}
void quan(int a[], int b[], int m, int j)//围圈
{
int i;
for(i = 1; i < m; i ++)
{
if(a[i] != b[j] && sushu(b[j] + a[i]) && a[i] != 0)
{
b[++ j] = a[i];//如果满足条件就将a[i]加到数组b中。
a[i] = 0;//同时将a[i]变成0
quan(a, b, m, j);//继续
}
}
}
int main()
{
int a[20], b[20], i, j;
printf("*******初始化数组**********\n");
for(i = 0; i < 20; i ++)
a[i] = i + 1;
j = 0;
b[j] = a[0];//将b[0]初始化为a[0]
a[0] = 0;

printf("b[%d] = %d\n",j,b[j]);

quan(a, b, 20, j);
printf("\n");
printf("*******围成的圈是**********\n");
for(i = 0; i < 20; i ++)
printf("%d ",b[i]);
printf("\n");
return 0;
}

运行的结果是
想了很久为什么会是这个结果,而且20 + 19 = 39明明是合数,却也将19加进b数组中去了。帮帮忙看一下~~,谢谢了哇~~

[解决办法]
题不是这样做的
要穷举写循环来判断每个是否合法
由于奇偶必须相隔,大概要循环10!*10!次
[解决办法]
还可以简化从1开始,那么下一个只能是(2,4,6,10,12,16,18), 依次计算所有符合条件的数顺序依次循环下去,直到满足条件为止,也许你还可以想出其他办法优化
[解决办法]
如下插入一条打印语句可知为何结果不对:
b[++ j] = a[i];//如果满足条件就将a[i]加到数组b中。
printf("b[%d]=%d\n", j, b[j]);

*******初始化数组**********
b[0] = 1
b[1]=2
b[2]=3
b[3]=4
b[4]=7
b[5]=6
b[6]=5
b[7]=8
b[8]=9
b[9]=10
b[10]=13
b[11]=16
b[12]=15
b[13]=14
b[14]=17
b[15]=12
b[16]=11
b[17]=18
b[18]=19
b[17]=20

*******围成的圈是**********
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 12 11 20 19 -858993460

由上可知,b[17]因递归返回写了2次。j最大达到18,因此b[19]没有赋过值,仍是编译器赋的值0xcccccccc,即-858993460。

LZ应考虑其它算法。


[解决办法]
LZ程序只试了1种排列,而且这个排列不能产生解。应该试多种排列,可按1楼所说完备地查找,也可试其他捷径。以下代码中的排列方法凑巧找到了一个解。

C/C++ code
#include <stdio.h>#include <math.h>bool sushu(int m)//判断是否是素数{  int i;  for(i = 2; i <= sqrt(m) ; i ++)  {    if(m % i == 0)      break;    else      continue;  }  if(i > sqrt(m))    return true;  else    return false;}int j;//加,把j移出递归以避免重复写b数组void quan(int a[], int b[], int m/*删, int j*/)//围圈{  int i;  for(i = 1; i < m; i ++)  {     if(a[i] != b[j] && sushu(b[j] + a[i]) && a[i] != 0)    {       b[++ j] = a[i];//如果满足条件就将a[i]加到数组b中。      a[i] = 0; //同时将a[i]变成0       quan(a, b, m/*删, j*/);//继续    }  }   }int main(){  int a[20], b[20], i/*删, j*/;  int k;//加  for (k = 0; k < 20; k++)//加  {    //printf("*******初始化数组**********\n");    for(i = 0; i < 20; i ++)//      a[i] = 20 - i;//改 a[i] = i + 1;    j = 0;    b[j] = a[k];//改 b[j] = a[0];//将b[0]初始化为a[0]    a[k] = 0;//改 a[0] = 0;      //删printf("b[%d] = %d\n",j,b[j]);       quan(a, b, 20/*删, j*/);    //删printf("\n");    if (j == 19)//加    {      printf("围成的圈是: ");      for(i = 0; i <= j; i ++)//改 for(i = 0; i < 20; i ++)        printf("%d ",b[i]);      printf("\n");    }  }  return 0;}
[解决办法]
#include<stdio.h>
#include<math.h>

#define N 20

bool Prime(int n)


{
int k = (int)sqrt(n);

for(int i = 2; i <= k; i ++)
{
if(n % i == 0)
{
return false;
}
}

return true;
}

bool Check(int a[], int n, int i)
{
for(int j = 0; j < n; j ++)
{
if(a[j] == i)
{
return false;
}
}

if(n < N-1)
{
return (Prime(a[n-1]+i));
}
else
{
return (Prime(a[0]+i) && Prime(a[n-1]+i));
}
}

void PrimeCircle(int a[], int n)
{
for(int i = 1; i <= N; i ++)
{
if(Check(a,n,i))
{
a[n] = i;

if(n == N-1)
{
for(int j = 0; j < N; j ++)
{
printf("%d ", a[j]);
}
printf("\n");
}
else
{
PrimeCircle(a, n+1);
}

a[n] = 0;
}
}
}

void main()
{
int a[N];

PrimeCircle(a, 0);
}
这个可以求出所有解,你看哈。
[解决办法]
#include<iostream>
using namespace std;
bool prime[40];
int a[21];
void dfs(int k,int n)
{
int i,j;
if(k==n&&prime[a[0]+a[n-1]]==0)
{
printf("1");
for(i=1;i<n;i++) printf(" %d",a[i]);
printf("\n");
return ;
}
else
for(i=2;i<=n;i++)
{
int ok=0;
a[k]=i;
for(j=0;j<k;j++)
if(a[j]==i||prime[i+a[k-1]]==1){ ok=1;break;}
if(ok==0) dfs(k+1,n);
}
}

int main()
{
int n,cnt=1,i,j;
for(i=3;i<40;i++)
for(j=2;j*j<=i;j++)
if(i%j==0) { prime[i]=1;break;}

while(scanf("%d",&n)!=EOF)
{

printf("Case %d:\n",cnt++);
a[0]=1;
dfs(1,n);
printf("\n");
}
return 0;
}
看了一下lz的
自己写了一个 通过测试了http://acm.hdu.edu.cn/diy/contest_search.php?action=go

读书人网 >C语言

热点推荐