很经典的一道素数环的题。
回溯法的基本思想
在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。(百度百科)
这道题的思想,就是搜到一个符合的数就放到数组a中,直到所有数都在数组中,然后把这个数组打印(相当于搜出了一个子树),然后逐层回溯,当再搜到符合条件的数时更新数组(相当于从这个位置从开一个叉树),直到所有可能的子树都被搜遍。
这里的数据不大,为了方便,先给素数打个表。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[30],vis[30],prime[50],n;
void isprime()
{
memset(prime,0,sizeof(prime));
for(int i=4; i<50; i++)
{
for(int j=2; j<25; j++)
{
if(i%j==0 && i!=j)
prime[i] = 1;
}
}
}
void dfs(int t)
{
if(t==n && !prime[1+a[t-1]])
{
printf("1");
for(int i=1; i<n; i++)
printf(" %d",a[i]);
printf("\n");
}
else
{
for(int i=2; i<=n; i++)
{
if(vis[i]==0 && !prime[i+a[t-1]])
{
a[t] = i;
vis[i] = 1;
dfs(t+1);
vis[i] = 0;
}
}
}
}
int main()
{
int cas=1;
isprime();
while(scanf("%d",&n) != EOF)
{
printf("Case %d:\n",cas++);
memset(vis,0,sizeof(vis));
memset(a,0,sizeof(a));
a[0]=1;
dfs(1);
printf("\n");
}
return 0;
}