#include <iostream>
using namespace std;
//用回溯法实现素数环
//输入正整数n把整数1,2,3...n组成一个环,使得相邻两个整数之和均为素数,
//输出时从整数1开始逆时针排序,同一个环应恰好输出一次。
// n <= 16
const int n = 6;
int vis[n+1] = {0}; //被访问过则为1没有被访问过为0
int A[n]; //储存数的放法
int isp[n*2] = {0};
void dfs(int cur)
{
//递归边界,记得要判断第一个数和最后一个数是否满足要求
if(cur == n && isp[A[0] + A[n-1]])
{
for(int i = 0; i < n; i++)
cout << A[i];
cout << endl;
}
else for(int i = 2; i <= n; i++) //放置每一个数字
if(!vis[i] && isp[i+A[cur-1]]) //如果i没有用过,并且与之前的一个数的和为素数
{
A[cur] = i;
vis[i] = 1; //设置使用标志
dfs(cur+1); //放下一个数
vis[i] = 0; //把使用过的标志改回来
}
}
//判断是否为素数
int is_prime(int x)
{
int i = 0;
for(i = 2; i < x/2; i++)
{
if(x%i == 0){
return 0;
}
}
return 1;
}
int main()
{
int i;
for(i = 0; i < 2*n; i++) isp[i] = is_prime(i); //构造素数表,在dfs中就可以直接使用
for(i = 0; i < n; i++) A[i] = i+1; //初始化A
dfs(1);
return 0;
}
//困难的串
//如果一个字符串包含两个相邻的重复子串,则称它是“容易的串
//其他船称为“困难的串”.例如,BB,ABCDACABCAB都是容易的
//D,DC,ABDAB都是困难的,输入正整数n和L,输出由前L个字符组成的,字典序dik小的困难的串
//例如,当L = 3时,前7个困难的串分别为:A,AB,ABA,ABAC,ABACA,ABACAB,ABACABA
const int n = 5;
int L; //由字典顺序的前L个字符组成
int S[n] = {0};
int dfs(int cur)
{
//递归边界
if(cur++ == n)
{
for(int i = 0; i < cur; i++) printf("%c", 'A'+S[i]);
printf("\n");
return 0;
}
//摆放第cur个字符的位置
for(int i = 0; i < L; i++)
{
S[cur] = i;
int ok = 1;
//尝试长度为j*2的后缀
for(int j = 1; j*2 <= cur+1; j++)
{
int equal = 1;
//判断
for(int k = 0; k < j; k++)
if(S[k] != S[cur-k-j]) {equal = 0; break;}
//如果后缀的后一半等于前一半不符合要求,就退出
if(equal) {ok = 0; break;}
}
if(ok) if(!dfs(cur+1)) return 0; //递归搜索,如果已经找到了解,就直接退出
}
return 1;
}
仅供个人参考,如有错误望指出!