UVa524 例题7-4 素数环 (Prime Ring Problem)

原题链接: UVa-524

题目大意:

 模输入正整数n,把整数1,2,3...,n,组成一个环,使得相邻的两个整数之和均为素数,输出从整数1开始逆时针排序。同一个环应恰好输出一次.n<=16。

                                  

解题思路:

 如果这道题是在紫书上看到的,那这道题应该也没什么问题(估计也不会看到我这篇博客)。因为这道题的整体框架和书上前面的引例——八皇后问题的回溯法解法大同小异。都是通过递归来枚举,并判断是否符合题意(环上前后两项之和为素数),当递归到解答树的叶子节点的时候进行输出。


 需要注意输出格式,另外还有一个小技巧,在判断是否已经放入环中的时候可以直接使用一个数组vis[i]来判断i是否在环中,在递归函数之后,需要记得将vis[i]恢复。不然会出错。


 另外,既然是环,如果使用是回溯法的框架的话,最后输出之前记得判断第1个和第n个之和是否为素数。


 看到OJ上排名前几的一个代码,直接把素数给列出来了,第一眼看上去:还有这操作?裁判他耍赖皮啊。仔细想想确实节约不少时间。。。

代码

#include<iostream>
#include<cstring>
#include<cmath>

using namespace std;

bool is_prime(int n);
void solve(int cur);

const int MAXN = 16 + 4;

int order[MAXN], vis[MAXN];//order:用来存储序列,记录第i个位置的数值;vis来记录i是否在已经在order中
int n;

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	int kase = 0;
	while (cin >> n) {
		if (kase++) cout << endl;
		cout << "Case " << kase << ":\n";
		memset(vis, 0, sizeof(vis));	//每一轮都要初始化vis 
		order[1] = 1;
		solve(2);
	}
	return 0;
}

void solve(int cur) 
{
	if (cur == n+1 && is_prime(order[1]+order[n])) { 	//输出之前要判断 order[1]+order[n]是否为质数 
		for (int i = 1; i <= n; i++) {
			if (i != 1) cout << " ";
			cout << order[i];
		}
		cout << endl;
	}
	else {
		for (int i = 2; i <= n; i++) {
			if (!vis[i] && is_prime(order[cur-1]+i)) { 	//既符合条件,又不在环中 
				vis[i] = 1;
				order[cur] = i;
				solve(cur+1);
				vis[i] = 0;				//要恢复全局变量 
			}
		}
	}
}

bool is_prime(int n)					//判断是否为素数(伪) 
{
	for (int i = 2; i <= sqrt(n)+1; i++)
		if (n%i == 0) return false;
	return true;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值