《算法之美》---DFS--素数环&困难串

素数环

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;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值