HDU 1016 Prime Ring Problem --- 经典DFS
题意:输入一个数n,把1到n的自然数放到一个环里(第一个为1),保证相邻的两个数的和是素数。
思路:第一个数填1,以后每个数判断该数和前一个数想加是否为素数,是则填,然后标记,近一步递归求解。 然后记得回溯,继续判断下一个和前一个数之和为素数的数。素数需要打表
/* HDU 1016 Prime Ring Problem --- 经典DFS */ #include <cstdio> #include <cstring> int n; bool primer[45], visit[25]; //primer打素数表,visit标记是否访问 int a[25]; //数组a存储放置的数 /* 40以内素数打表 */ void getPrimer(){ //因为n最大是20,所以只要打到40 primer[0] = primer[1] = 1; //1表示不是素数 for (int i = 2; i < 7; ++i){ for (int j = i*i; j < 40; j+=i){ primer[j] = 1; //1表示不是素数 }//for(j) }//for(i) } /*dfs搜索 num为已填的数的数目*/ void dfs(int num){ int i; //已全部填完且首位之和为素数 输出 if (num == n && !primer[a[num - 1] + a[0]]){ for (i = 0; i < num-1; ++i){ printf("%d ", a[i]); } printf("%d\n", a[i]); return; } else{ for (i = 2; i <= n; ++i){ //该数未用过且和上一个数之和为素数 if (!visit[i] && !primer[a[num - 1] + i]){ a[num] = i; visit[i] = 1; dfs(num + 1); //递归填数 visit[i] = 0; //回溯 } } } } int main() { int kase = 0; getPrimer(); while (scanf("%d", &n) == 1){ memset(visit, 0, sizeof visit); printf("Case %d:\n", ++kase); visit[1] = 1; //1用过 a[0] = 1; //第一个数是1 dfs(1); printf("\n"); } return 0; }