原创于11.30日午夜。
问题描述:
素数环问题。
有一个环是由n个圆圈组成(n为偶数),我们想把1到n之间的n个自然数放在这些空的圆圈中,使得相邻两个圆圈的数之和为一素数。注意第一个圆圈的数一定是1,下面以n=6实例:
输入说明: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
解决方案详述:
素数环算法原理图如下:
以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; } | |