【原创】素数环问题求解探讨

原创于11.30日午夜。

问题描述:

素数环问题。

 有一个环是由n个圆圈组成(n为偶数),我们想把1到n之间的n个自然数放在这些空的圆圈中,使得相邻两个圆圈的数之和为一素数。注意第一个圆圈的数一定是1,下面以n=6实例:

   

2ae983197f82954842a9ad74.jpg
输入说明 : 0<n<=16

输出说明:输出的每一列就是圆圈中的数字,从1开始顺时针方向旋转。输出要求必须满足以上要求。

输入用例

6

8

输出用例

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

解决方案详述:

素数环算法原理图如下:
232400_518629138.jpg
以4个数为例。首先第一个为1,接下来从其他未选过的值中按从小到大选取下个节点值,选好后判断它和上个节点的和是否为素数,如果不为素数则此节点选取下个值,如果是素数则走向下个节点。
本例中则第二节点为2,1+2为素数,所以走向第三个节点,再遵循前面的规则,选第三节点值为3,2+3为素数,走向节点4,前面没有选的值只有4,因此 选取4作为节点4的值,3+4为素数,当遇到最后一个节点时还要判断它和第一个节点的和是否为素数,由于4+1为素数且已经达到最后节点,因此输出此次循 环的最终值:1,2,3,4.
然后开始回溯。回到上个节点,对节点取另一个值(由小到大且不和原先选过的重复),然后继续按照前述规则判断。
本例中,回到第三节点,上次选取值为3,比它大且按顺序没选过的值为4,但2+4不是素数,且4是最后一个可选的数,因此不用继续下去了,开始回溯。回到 第二节点,选取节点值为3,但1+3不是素数,第二节点再次选取下一个值4,1+4为素数,走向下个节点第三节点,选其值为2,但2+4不为素数,第三节 点选取下个值3,3+4为素数,走向下个节点,第四节点,只有2可选,3+2为素数,由于到达末节点,输出所有节点值:1,4,3,2.
然后再回溯到第三节点,由于已无值可选,在回溯到第二节点,也是无值可选,于是回溯到第一节点,由于到达顶节点,过程结束。
此算法最坏时间复杂度为 (N-1)!,由于复杂度很大,所以此算法还有待改进。有待大家一起来找到更优化的算法。谢谢!

 

源代码:

 

 

public class Algorithm_Collections
{
&<60;&<60; &<60;&<60;&<60; public bool IsPrime(int num)
&<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; for (int i = 2; i <= (int)Math.Sqrt(num) ; i++)
&<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; if (num % i == 0)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; return false;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; return true;
&<60;&<60; &<60;&<60;&<60; }

&<60;&<60; &<60;&<60;&<60; public void FindPrimeCycle(int myNums)
&<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; int[] cyc_array = new int[myNums];
&<60;&<60; &<60;&<60; &<60;&<60; int i = 1;
&<60;&<60; &<60;&<60; &<60;&<60; int j = 2;
&<60;&<60; &<60;&<60; &<60;&<60; //设置第一个元素始终为1
&<60;&<60; &<60;&<60; &<60;&<60; cyc_array[0] = 1;
&<60;&<60; &<60;&<60; &<60;&<60; long cyc_times = 0;
&<60;&<60; &<60;&<60; &<60;&<60; while (i != 0)
&<60;&<60; &<60;&<60; &<60;&<60; {//用回溯法找满足要求的,当i=0时结束回溯
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; cyc_times++;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; cyc_array = j;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //判断此节点取值是否和前面的节点取值重复
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; for (int k = 0; k < i; k++)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; //重复则更换取值并退出for循环
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; if (cyc_array == cyc_array[k])
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; j++;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; break;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //判断取值是否越界,越界则表明当前节点循环已结束,回溯到上个节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; if (j == myNums + 1)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; i--;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; j = cyc_array + 1;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //这里是根据前面的for判断结果来判断取值是否和前面的重复,重复则重新取值
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; if (cyc_array != j)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; continue;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //判断是否已经走完所有节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; if (i == myNums - 1)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; //将最后一个取值分别和它前面的一个值和第一个值相加看是否为素数,是则已完成一次满足条件的所有循环,输出满足条件的值
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; if (IsPrime(cyc_array[i - 1] + cyc_array) && IsPrime(cyc_array[0] + cyc_array))
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; Console.Write("\n{0}", cyc_array[0]);
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; for (int k = 1; k < myNums; k++)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; Console.Write("-{0}-", cyc_array[k]);
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }

&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; //回溯到上个节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; i--;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; j = cyc_array + 1;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //没有走完所有节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; else
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; //相邻之和为素数则走向下个节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; if (IsPrime(cyc_array[i - 1] + cyc_array))
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; i++;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; j = 2;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; else
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //相邻之和不为素数且此节点已经试过所有取值,则回溯到上一个节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; if (cyc_array >= myNums)
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; i--;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; j = cyc_array + 1;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; //相邻之和不为素数且此节点还有没有取过的值,则更换取值继续当前节点
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; else
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; j++;
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60;&<60; }

&<60;&<60; &<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; }
&<60;&<60; &<60;&<60; &<60;&<60; Console.WriteLine("\n{0}",cyc_times);
&<60;&<60; &<60;&<60;&<60; }
&<60;&<60; &<60;&<60;&<60; public static void Main()
&<60;&<60; &<60;&<60;&<60; {
&<60;&<60; &<60;&<60; &<60;&<60; int myNums;
&<60;&<60; &<60;&<60; &<60;&<60; myNums = int.Parse(Console.ReadLine());
&<60;&<60; &<60;&<60; &<60;&<60;&<60;
&<60;&<60; &<60;&<60; &<60;&<60; Console.Write("{0} nums you input.", myNums);
&<60;&<60; &<60;&<60; &<60;&<60; Algorithm_Collections myAlgCollection = new Algorithm_Collections(0);
&<60;&<60; &<60;&<60; &<60;&<60; myAlgCollection.FindPrimeCycle(myNums);
&<60;&<60; &<60;&<60; &<60;&<60; Console.WriteLine();
&<60;&<60; &<60;&<60; &<60;&<60; Console.Read();
&<60;&<60; &<60;&<60;
&<60;&<60; &<60;&<60;&<60; }
&<60;&<60; }

转载于:https://www.cnblogs.com/absolute8511/archive/2007/11/30/1649665.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[2\]的代码,这是一个解决"素数"问题的算法。该问题要求找到一个由1到n这些数组成的,使得中相邻两个数之和都是素数。算法使用了深度优先搜索的思想,先选定一个数,然后递归地选择下一个数,直到找到一个满足条件的。在递归过程中,使用了一个数组来记录已经选择的数,以及一个布尔数组来标记是否已经访问过某个数。同时,还使用了一个函数来判断一个数是否是素数。 根据引用\[3\]的输出示例,当n=4时,可能的素数有8个,分别是: 1: 1 2 3 4 2: 1 4 3 2 3: 2 1 4 3 4: 2 3 4 1 5: 3 2 1 4 6: 3 4 1 2 7: 4 1 2 3 8: 4 3 2 1 因此,对于问题"1358 - 素数",当n=4时,总共有8个满足条件的素数。 #### 引用[.reference_title] - *1* [【DFS练习】素数](https://blog.csdn.net/z135733/article/details/122742948)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [1358 - 【提高】素数](https://blog.csdn.net/PanDaoxi2020/article/details/126597717)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值