【Java与数学】将ABCDE排成一列,要求ACE三人在排列中顺序为“ACE”或“ECA”,三人可以不相邻,请列出符合条件的排列

【数学思路】

可以把题目简化成BD两人插ACE中的空缺。

当ACE三人已经拍好ACE的顺序,B插进去三人队列的4个空,D再插进去四人队列的5个空,这一类有4*5=20种情况;

当ACE三人已经拍好ECA的顺序,B插进去三人队列的4个空,D再插进去四人队列的5个空,这一类也有4*5=20种情况;

合计=20+20=40种情况。

【程序思路】

将ABCDE五人进行全排列,然后把ACE三人的序号累加到一个字符串里,如果这个字符串是ACE或是ECA则符合条件。

【代码】

辅助类Arranger:

import java.util.ArrayList;
import java.util.List;

/**
 * 用于产生排列结果的工具类
 * 从n个元素中取出m个元素,按照一定的顺序排成一列。得到所有排列的方案
 */
class Arranger {
    // 保存在内部的对原始元素数组的引用
    private int[] arr;

    // 总计多少元素,此即数组长度
    private final int n;

    // 选多少个
    private final int m;

    // 返回结果
    private List<List<Integer>> results;

    /**
     * 构造函数一
     * 这个构造函数是用于全排列的(n=m=数组长度)
     *
     * @arr 原始元素数组
     */
    public Arranger(int[] arr) {
        this.arr = arr;
        this.n = arr.length;
        this.m = arr.length;

        this.results = new ArrayList<>();
        doArrange(new ArrayList<>());
    }

    /**
     * 构造函数二
     * 这个构造函数是用于部分排列的(m<n=数组长度)
     *
     * @param arr    原始元素数组
     * @param selCnt 选多少个
     */
    public Arranger(int[] arr, int selCnt) {
        this.arr = arr;
        this.n = arr.length;
        this.m = selCnt;
        if (m > n) {
            throw new ArrayIndexOutOfBoundsException("m:" + m + " >n:" + n);
        }

        this.results = new ArrayList<>();
        doArrange(new ArrayList<>());
    }

    /**
     * 使用递归进行全排列,结果放在results中
     *
     * @param initialList 初始链表
     */
    private void doArrange(List<Integer> initialList) {
        List<Integer> innerList = new ArrayList<>(initialList);

        if (m == initialList.size()) {
            results.add(innerList);
        }

        for (int i = 0; i < arr.length; i++) {
            if (innerList.contains(arr[i])) {
                continue;
            }

            innerList.add(arr[i]);
            doArrange(innerList);
            innerList.remove(innerList.size() - 1);
        }
    }

    /**
     * 获得结果链表的引用
     *
     * @return
     */
    public List<List<Integer>> getResults() {
        return results;
    }

    // 测试
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4};
        Arranger arranger = new Arranger(numbers);

        System.out.println("四元素全排列示例:");
        int idx = 0;
        for (List<Integer> re : arranger.getResults()) {
            System.out.println(String.format("%02d", ++idx) + "." + re);
        }

        /*Arranger arranger2 = new Arranger(numbers, 2);
        System.out.println("\n四选二排列示例:");
        idx = 0;
        for (List<Integer> re : arranger2.getResults()) {
            System.out.println(String.format("%02d", ++idx) + "." + re);
        }*/
    }
}

主类FixedLine:

import java.util.List;

/**
 * 将ABCDE排成一列,要求ACE三人在排列中顺序为“ACE”或“ECA”,三人可以不相邻
 * 列出符合条件的排列
 * @author 逆火
 *
 */
public class FixedLine {
    public static void main(String[] args) {
        final String[] names= {"A","B","C","D","E"};
        int[] numbers = {0, 1, 2, 3, 4};
        Arranger arranger = new Arranger(numbers);

        int idx = 0;
        for (List<Integer> line : arranger.getResults()) {
            
            String sentence="";
            String order="";
            for(int i:line) {
                if(i==0 || i==2 || i==4) {
                    order+=i;
                }
                
                sentence+=names[i]+",";
            }
            
            if("024".equals(order) || "420".equals(order)) {
                System.out.println(String.format("%02d", ++idx) + "." + sentence);
            }
        }
    }
}

【输出】

01.A,B,C,D,E,
02.A,B,C,E,D,
03.A,B,D,C,E,
04.A,C,B,D,E,
05.A,C,B,E,D,
06.A,C,D,B,E,
07.A,C,D,E,B,
08.A,C,E,B,D,
09.A,C,E,D,B,
10.A,D,B,C,E,
11.A,D,C,B,E,
12.A,D,C,E,B,
13.B,A,C,D,E,
14.B,A,C,E,D,
15.B,A,D,C,E,
16.B,D,A,C,E,
17.B,D,E,C,A,
18.B,E,C,A,D,
19.B,E,C,D,A,
20.B,E,D,C,A,
21.D,A,B,C,E,
22.D,A,C,B,E,
23.D,A,C,E,B,
24.D,B,A,C,E,
25.D,B,E,C,A,
26.D,E,B,C,A,
27.D,E,C,A,B,
28.D,E,C,B,A,
29.E,B,C,A,D,
30.E,B,C,D,A,
31.E,B,D,C,A,
32.E,C,A,B,D,
33.E,C,A,D,B,
34.E,C,B,A,D,
35.E,C,B,D,A,
36.E,C,D,A,B,
37.E,C,D,B,A,
38.E,D,B,C,A,
39.E,D,C,A,B,
40.E,D,C,B,A,

【结语】

数学方法和程序思路不同而结果又可以相互印证,可以相互证明对方的正确性。

END

posted @ 2017-09-02 18:11  逆火狂飙  阅读(331)  评论(0编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东