回溯法实现素数环和困难的串问题

#include
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; 
 }

仅供个人参考,如有错误望指出!

你可能感兴趣的:(回溯法实现素数环和困难的串问题)