例题 7-4 素数环(Peime Ring Problem, Uva 524)

题目

题目传送门

啊咧

提交代码的时候,第一次PE错误,我想了一下可能是 行末打回车前的空格在作怪,一改,还真是。
输出结果的末尾打空格也是不行的,比赛要注意咯。

2020/4/6补充 : 代码测试时间(没错,1000多将近2000的当然是我的思路啦)
在这里插入图片描述

AC代码

//4/1/20:09 _  20:40 
//@reasonbao
//comn on, you guy! do it!
#include <iostream>
#include <cstdio>

using namespace std;

bool PrimeJudge(int n) {
	bool is_prime = true;
	for (int i = 2; i <= n-1; i++) {
		if (n % i == 0) {
			is_prime = false;
			break;
		}
	}
	return is_prime;
}
//回溯法 
void Operate(int n, int *A, int cur) {
	if (cur == n) {		//能递归到这,说明满足条件	
		for (int i = 0; i < n; i++) {
//			cout << A[i] << " ";		PE错误 
			if (i != n-1) cout << A[i] << " ";
			else cout << A[i] << endl;
		}
//		cout << endl;
	}
	for (int i = 2; i <= n; i++) {	//A[cur] 尝试填入各种情况 
		bool is_ok = true;
		for (int j = 0; j < cur; j++) {
			if (i == A[j] ) {		//填过的情况 
				is_ok = false;
				break;
			}
			if (!PrimeJudge(A[cur-1] + i)) {	//与前一个数相加 非素数情况 
				is_ok = false;
				break;
			}
		}
		if (cur == n-1) {		//填最后一个数的情况,判断首尾相加是否素数
			if (!PrimeJudge(i + A[0])) is_ok = false;				 
		}
		
		if (is_ok) {
			A[cur] = i;
			Operate(n,A,cur+1);
		}
	}
}

int main() {
	int A[20];
	int n;
	int kase = 0;
	while (scanf("%d", &n) != EOF) {
		kase++;
		if (kase > 1) cout << endl;
//		cout << PrimeJudge(n) << endl;
		printf("Case %d:\n", kase);
		A[0] = 1;	//枚举以1开头的情况即可
		Operate(n, A, 1);
	}
	return 0;
}

代码2.0 学习了刘汝佳的思路,十分清晰明了,而且Time直接180ms了

//4/6 15:30
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 16;
int vis[maxn];	//数字是否使用过的标志  

int is_prime(int n) {
	if (n<=1 ) return 0;
	for (int i = 2; i <= n-1; i++) {	//素数判断只要遍历到开方处就行了 
		if (n % i == 0) {
			return 0;
		}
	}
	return 1; 
}
//生成-测试法的最坏情况非常大,故采用回溯法 
void Operate(int n, int *A, int cur) {
	if (cur == n && is_prime(A[0] + A[n-1])) {								//注意还没判断头尾	
		for (int i = 0; i < n; i++) {
			if (i != n-1) printf("%d ", A[i]);	//速度快,相比 cout 
			else printf("%d\n", A[i]);
		}
	}
	else {
		for (int i = 2; i <= n; i++) {	//往A[i]中填入各种情况 
			if (!vis[i] && is_prime(A[cur-1] + i)) {
				A[cur] = i;
				vis[i] = 1;
				Operate(n,A,cur+1);
				vis[i] = 0;		//用完即空闲,置为0 
			}
		}
	}
}

int main() {
	int A[maxn];
	int n;
	int kase = 0;
	while (scanf("%d", &n) != EOF) {
		kase++;
		if (kase > 1) printf("\n");
		printf("Case %d:\n", kase);
		memset(vis,0,sizeof(vis)); 
		A[0] = 1;	//枚举以1开头的情况即可
		Operate(n, A, 1);
	}
	return 0;
}

代码3.0 TQL,再补充了刘汝佳老师的思路,Time = 110ms了

//4/6 15:30
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath> 

using namespace std;

const int maxn = 16;
int g_vis[maxn];	//数字是否使用过的标志  
int g_isp[maxn*2];	//素数表 

int is_prime(int n) {
	if (n<=1 ) return 0;
	for (int i = 2; i <= floor(sqrt(n) + 0.5); i++) {	//素数判断只要遍历到开方处就行了 
		if (n % i == 0) {								//floor()-向下取整,当n较大时可避免整数变成xxx.9999 
			return 0;
		}
	}
	return 1; 
}
//生成-测试法的最坏情况非常大,故采用回溯法 
void Operate(int n, int *A, int cur) {
	if (cur == n && g_isp[A[0] + A[n-1]]) {								//注意还没判断头尾	
		for (int i = 0; i < n; i++) {
			if (i != n-1) printf("%d ", A[i]);	//速度快,相比 cout 
			else printf("%d\n", A[i]);
		}
	}
	else {
		for (int i = 2; i <= n; i++) {	//往A[i]中填入各种情况 
			if (!g_vis[i] && g_isp[A[cur-1] + i]) {
				A[cur] = i;
				g_vis[i] = 1;
				Operate(n,A,cur+1);
				g_vis[i] = 0;		//用完即空闲,置为0 
			}
		}
	}
}

int main() {
	int A[maxn];
	int n;
	int kase = 0;
	//生成素数表 
	for (int i = 0; i < maxn*2; i++) {
		g_isp[i] = is_prime(i);
	} 
	while (scanf("%d", &n) != EOF) {
		kase++;
		if (kase > 1) printf("\n");
		printf("Case %d:\n", kase);
		memset(g_vis,0,sizeof(g_vis)); 
		A[0] = 1;	//枚举以1开头的情况即可
		Operate(n, A, 1);
	}
	return 0;
}
发布了41 篇原创文章 · 获赞 2 · 访问量 1637

猜你喜欢

转载自blog.csdn.net/qq_44296342/article/details/105278843
今日推荐