素数环

import java.util.Scanner;

/** * 输入正整数n,对1-n进行排列,使得相邻两个数之和均为素数, * 输出时从整数1开始,逆时针排列。同一个环应恰好输出一次。 * n<=16 * * 如输入:6 * 输出: * 1 4 3 2 5 6 * 1 6 5 2 3 4 */
public class Dfs_5素数环 {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int[] r = new int[n];
    r[0] = 1;
    dfs(n, r, 1);
  }

  private static void dfs(int n, int[] r, int cur) {
    if (cur == n && isP(r[0] + r[n - 1])) {//填到末尾了,还有首尾相加为素数才算成功
      print(r);
      return;
    }

    for (int i = 2; i <= n; i++) {//尝试用每个数字填到cur这个位置
      if (check(r, i, cur)) {//r中没有i这个数,且和上一个数之和为素数
        r[cur] = i;//试着将i放在cur位置,往前走一步
        dfs(n, r, cur + 1);
        r[cur] = 0;//回溯
      }

    }
  }

  private static void print(int[] r) {
    for (int i = 0; i < r.length; i++) {
      System.out.print(r[i] + (i == r.length - 1 ? "" : " "));
    }
    System.out.println();
  }

  private static boolean check(int[] r, int i, int cur) {
    for (int e : r) {
      if (e == i || !isP(r[cur - 1] + i)) return false;
    }
    return true;
  }

  private static boolean isP(int k) {
    for (int i = 2; i * i <= k; i++) {
      if (k % i == 0) return false;
    }
    return true;

  }
}
public class Main {
    private static int[] visit;

    public static void main(String[] args) {
        count(6);
    }

    private static void count(int n) {

        int res[] = new int[n];
        res[0] = 1;
        visit = new int[n + 1];
        visit[1] = 1;
        dfs(res, 1, n);
    }

    private static void dfs(int[] res, int cur, int n) {
        if (cur == n) {
            if (check(res[0], res[n - 1])){
                for (int re : res) {
                    System.out.printf("%d",re);
                }
                System.out.println();
            }
        }


        for (int j = 2; j <= n; j++) {
            if (visit[j] == 1) {
                continue;
            }
            if (check(j, res[cur - 1])) {
                visit[j] = 1;
                res[cur] = j;
                dfs(res, cur + 1, n);
                visit[j] = 0;
                res[cur] = 0;
            }
        }

    }

    private static boolean check(int x, int y) {
        int num = x + y;
        for (int i = 2; i * i <= num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }


}

困难串

/** * 问题描述:如果一个字符串包含两个相邻的重复子串,则称它为容易的串,其他串称为困难的串, * 如:BB,ABCDACABCAB,ABCDABCD都是容易的,A,AB,ABA,D,DC,ABDAB,CBABCBA都是困难的。 输入正整数n,L,输出由前L个字符(大写英文字母)组成的,字典序第n小的困难的串。 例如,当L=3时,前7个困难的串分别为: A,AB,ABA,ABAC,ABACA,ABACAB,ABACABA n指定为4的话,输出ABAC */
public class Dfs_6_困难的串 {
  public static void main(String[] args) {
    int n = 10;
    int l = 4;
    dfs(l, n, "");
    // isHard("0123020120",1);
  }

  static int count;

  private static void dfs(int l, int n, String prefix) {

    //尝试在prefix后追加一个字符
    for (char i = 'A'; i < 'A' + l; i++) {
      if (isHard(prefix, i)) {//是困难的串,就组合起来输出
        String x = prefix + i;
        System.out.println(x);
        count++;//计数
        if (count == n)
          System.exit(0);

        dfs(l, n, x);
      }
    }
  }

  /** * 判断prefix+i是否一个困难的串 * 1.遍历所有的长度为偶数的子串,看是否对称 * 2.prefix是一个困难的串 ABACA i * @param prefix * @param i * @return */
  private static boolean isHard(String prefix, char i) {
    int count = 0;//截取的宽度
    for (int j = prefix.length() - 1; j >= 0; j -= 2) {
      final String s1 = prefix.substring(j, j + count + 1);
      final String s2 = prefix.substring(j + count + 1) + i;
      if (s1.equals(s2))
        return false;
      count++;
    }
    return true;
  }
}