素数环问题

31 篇文章 0 订阅

问题:输入正整数n,把整数1,2,3,…,n组成一个环,使得相邻两个整数之和均为素数。输出时从整数1开始逆时针排列。n<=16;

样例输入:

6

样例输出:

1 4 3 2 5 6

1 6 5 2 3 4

方法一:直接枚举法

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int isp[200],A[200];
int is_prime(int n)
{
	int flag, i;
	flag = 1;
	for (i = 2; i <=sqrt(n);i++)
	if (n%i == 0){flag = 0;	break;}
	return flag;
}
int main()
{
	int n;
	cin >> n;
	for (int i = 2; i <= 20; i++)isp[i] = is_prime(i);
	for (int i = 0; i < n; i++)A[i] = i + 1;
	do{
		int ok = 1;
		for (int i = 0; i < n; i++)if (!isp[A[i] + A[(i + 1) % n]]){ ok = 0; break; }
		if (ok){
			for (int i = 0; i < n; i++)printf("%d ", A[i]);
			printf("\n");
		}
	} while (next_permutation(A + 1, A + n));
	system("pause");
	return 0;
}

程序的基本思路是保留1的位置不变,其他数字不断生成全排列,然后判断该序列是否符合要求,如果符合就输出。然而,该方法虽然比较直观,但效率比较差,当n为12时就已经很慢了。

方法2:回溯法

程序如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int isp[200],A[200],vis[200];
int n;
int is_prime(int n)
{
	int flag, i;
	flag = 1;
	for (i = 2; i <=sqrt(n);i++)
	if (n%i == 0){flag = 0;	break;}
	return flag;
} 

void dfs(int cur){
	if (cur == n&&isp[A[0] + A[n - 1]]){
		for (int i = 0; i < n; i++)printf("%d ", A[i]);
		printf("\n");
	}
	else for(int i =2; i <= n;i++)
	if (!vis[i] && isp[i + A[cur - 1]]){
		A[cur] = i;
		vis[i] = 1;
		dfs(cur+1);
		vis[i] = 0;
	}
}
int main()
{
	cin >> n;
	for (int i = 2; i <= 20; i++)isp[i] = is_prime(i);
	A[0] = 1;
	dfs(1);
	system("pause");
	return 0;
}

由于前面已经画了类似流程图,这里不再画。简单来说,每次递归的过程就是在一个解答树的分支中不断尝试剩下的元素,如果能符合要求,就放到素数环里面。素数环与之前唯一不同之处在于A[0]是确定为1的,只需确定1除外的其他元素的位置。


  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值