Regionals 1996 >> Asia - Shanghai
问题链接:UVa524 UVALive5270 HDU1016 ZOJ1457 Prime Ring Problem。
问题简述:输入一个数n(0<n<20),用1到n的整数围成一个圈,使得相邻的两个数之和为素数,输出各种可能的圈。
本题可以使用深度优先搜索求解。程序中,函数dfs()的参数为已经有几个数满足相邻为素数,其功能是寻找下一个满足条件的数。
问题分析:因为是一个圈,并且用1到n的整数都要被用到,所以将1固定在一个位置上。这样做也可以减少重复的搜索。
程序说明:
需要注意的是,HDU1016的格式与UVA524的格式略为不同,空行的位置不同。
对于HDU1016与UVA524,分别编写了一个根据快速简洁的C++的版本。
AC的C++语言程序如下(HDU1016,快速简洁版):
/* HDU1016 Prime Ring Problem */ #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> using namespace std; #define N 20 int prime[N * 2]; int ans[N]; int visited[N]; int n, flag; // Eratosthenes筛选法 void sieveofe(int p[], int n) { int i, j; p[0] = 0; p[1] = 0; p[2] = 1; // 初始化 for(i=3; i<n; i++) { p[i++] = 1; p[i] = 0; } int max = sqrt(n); for(i=3; i<=max; i++){ if(p[i]) { for(j=i+i; j<=n; j+=i) //进行筛选 p[j]=0; } } } void print_result() { int i; for(i=1; i<=n; i++) { if(i != 1) printf(" "); printf("%d", ans[i]); } printf(" "); } void dfs(int count) { int i; if(count == n) { if(prime[ans[count] + ans[1]]) print_result(); // 输出结果 } else { for(i=2; i<=n; i++) if(!visited[i] && prime[i + ans[count]]) { ans[count + 1] = i; visited[i] = 1; dfs(count + 1); visited[i] = 0; } } } int main(void) { sieveofe(prime, N * 2 -1); int caseno=0; while(scanf("%d", &n) != EOF) { // 初始化标志 memset(visited, 0, sizeof(visited)); printf("Case %d: ",++caseno); // 深度优先搜索并且输出结果 ans[1] = 1; visited[1] = 1; flag = 1; dfs(1); printf(" "); } return 0; }
AC的C语言程序如下(HDU1016):
/* HDU1016 ZOJ1457 Prime Ring Problem */ #include <stdio.h> #include <memory.h> #include <math.h> #define MAXN 20 int ans[MAXN]; int visit[MAXN]; int n, count; // 试除法判断一个数是否为素数 int isprime(int n) { if((n & 1) == 0) // 偶数:n % 2 == 0 return 0; if(n == 3) return 1; int end = sqrt(n), i; for(i=3; i<=end; i+=2) { if(n % i == 0) break; } return i > end ? 1 : 0; } void print_result() { int i; for(i=1; i<=n; i++) { if(i != 1) printf(" "); printf("%d", ans[i]); } printf(" "); } void dfs(int count) { int i; for(i=2; i<=n; i++) if(!visit[i]) { if(isprime(ans[count] + i)) { count++; if(count == n) { if(isprime(i + ans[1])) { ans[count] = i; print_result(); // 输出结果 } } else { ans[count] = i; visit[i] = 1; dfs(count); visit[i] = 0; } count--; } } } int main(void) { int caseno=0; while(scanf("%d", &n) != EOF) { // 初始化标志 memset(visit, 0, sizeof(visit)); printf("Case %d: ",++caseno); // 深度优先搜索并且输出结果 count = 1; ans[1] = 1; visit[1] = 1; dfs(count); printf(" "); } return 0; }
AC的C++语言程序如下(UVA524,快速简洁版):
/* UVA524 UVAlive5270 Prime Ring Problem */ #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> using namespace std; #define N 20 int prime[N * 2]; int ans[N]; int visited[N]; int n, flag; // Eratosthenes筛选法 void sieveofe(int p[], int n) { int i, j; p[0] = 0; p[1] = 0; p[2] = 1; // 初始化 for(i=3; i<n; i++) { p[i++] = 1; p[i] = 0; } int max = sqrt(n); for(i=3; i<=max; i++){ if(p[i]) { for(j=i+i; j<=n; j+=i) //进行筛选 p[j]=0; } } } void print_result() { int i; for(i=1; i<=n; i++) { if(i != 1) printf(" "); printf("%d", ans[i]); } printf(" "); } void dfs(int count) { int i; if(count == n) { if(prime[ans[count] + ans[1]]) print_result(); // 输出结果 } else { for(i=2; i<=n; i++) if(!visited[i] && prime[i + ans[count]]) { ans[count + 1] = i; visited[i] = 1; dfs(count + 1); visited[i] = 0; } } } int main(void) { sieveofe(prime, N * 2 -1); int caseno=0; while(scanf("%d", &n) != EOF) { // 初始化标志 memset(visited, 0, sizeof(visited)); if(caseno != 0) printf(" "); printf("Case %d: ",++caseno); // 深度优先搜索并且输出结果 ans[1] = 1; visited[1] = 1; flag = 1; dfs(1); } return 0; }
AC的C语言程序如下(UVA524):
/* UVA524 UVALive5270 Prime Ring Problem */ #include <stdio.h> #include <memory.h> #include <math.h> #define MAXN 20 int ans[MAXN]; int visit[MAXN]; int n, count; // 试除法判断一个数是否为素数 int isprime(int n) { if((n & 1) == 0) // 偶数:n % 2 == 0 return 0; if(n == 3) return 1; int end = sqrt(n), i; for(i=3; i<=end; i+=2) { if(n % i == 0) break; } return i > end ? 1 : 0; } void print_result() { int i; for(i=1; i<=n; i++) { if(i != 1) printf(" "); printf("%d", ans[i]); } printf(" "); } void dfs(int count) { int i; for(i=2; i<=n; i++) if(!visit[i]) { if(isprime(ans[count] + i)) { count++; if(count == n) { if(isprime(i + ans[1])) { ans[count] = i; print_result(); // 输出结果 } } else { ans[count] = i; visit[i] = 1; dfs(count); visit[i] = 0; } count--; } } } int main(void) { int caseno=0; while(scanf("%d", &n) != EOF) { // 初始化标志 memset(visit, 0, sizeof(visit)); if(caseno != 0) printf(" "); printf("Case %d: ",++caseno); // 深度优先搜索并且输出结果 count = 1; ans[1] = 1; visit[1] = 1; dfs(count); } return 0; }