全排列——回溯法

全排列

  • 求全排列:全排列指的是:n个元素中取n个元素(全部元素)的所有排列组合情况。
  • 求组合:n个元素,取m个元素(m<=n)的所有组合情况
  • 求子集:n个元素的所有子集(所有的组合情况)

全排列常用解决方法:回溯法和邻里交换法 

回溯:一般解决搜索问题,全排列也是一种搜索问题。

  • 回溯:就是类似枚举的搜索尝试过程。在搜索过程中寻找问题的解。当发现不满足求解的条件时返回,尝试别的路径。

全排列可以使用试探的办法列举所有的可能性。一个长度为n的序列,所有的排列组合:n!

  1. 从集合中选取一个元素(n种情况),并标记该元素已经被使用。
  2. 在第一步的基础上递归到下一层,从剩余的n-1个元素中,按照第一步的方法再找到一个元素,重复(1)
  3. 依次类推,所有的元素都被标记,将元素存起来,取对比求解的情况

例题:

1.

A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下图就是一种排法。

      A
     9 6
    4   8
   3 7 5 2

这样的排法可能会有很多。

如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?

public class Main {
    static int num[] = new int [10];
    static boolean bool[] = new boolean[10];
    static  int cnt = 0;
    public static void main(String[] args) {
        dfs(1);
        System.out.println(cnt/6);  //3种镜像、3种旋转
    }
    public static void dfs(int n){
        if(n==10){
            if(num[1]+num[2]+num[3]+num[4]==num[4]+num[5]+num[6]+num[7]&& 
                    num[4]+num[5]+num[6]+num[7]==num[7]+num[8]+num[9]+num[1]){
                cnt++;
            }
        }
        for(int i = 1; i < 10; i++){
            if(!bool[i]){
                bool[i]=true;
                num[n] = i;
                dfs(n+1);
                bool[i]=false;
            }
        }

    }
}