【高中数学/排列组合】我国古代将“礼乐射御书数”合称六艺,某校国学社团计划开展六艺讲座活动,要求活动当天每一艺安排一节,连拍六节,且数必须排在第三节,射和御相邻,则不同的安排顺序共有几种?
【原题】
我国古代将“礼乐射御书数”合称六艺,某校国学社团计划开展六艺讲座活动,要求活动当天每一艺安排一节,连拍六节,且数必须排在第三节,射和御相邻,则不同的安排顺序共有几种?
【解答】
既然数被卡死在第三节,往下就不用考虑它了。
第1种情况,射御占一二节,射御全排,下午三节全排列,那么有A_2_2*A_3_3种;
第2种情况,射御占四五节,射御全排,其它三节全排列,那么也有A_2_2*A_3_3种;
第3种情况,射御占五六节,射御全排,其它三节全排列,那么还是A_2_2*A_3_3种;
综上,总数=3*A_2_2*A_3_3=3*2*6=36种。
【程序解法】
程序解法不能和数学解法一个思路,否则就失去了可印证性。
程序解法可以让六艺全排,然后去除数不在第三位以及射御不在一起的情况。
主类代码:
package test240809; import java.util.List; /** * 六艺排课 *我国古代将“礼乐射御书数”合称六艺,某校国学社团计划开展六艺讲座活动,要求活动当天每一艺安排一节,连拍六节,且数必须排在第三节,射和御相邻,则不同的安排顺序共有几种? */ public class Test3 { public static void main(String[] args) { final String[] names= {"礼","乐","射","御","书","数"}; final int[] arr1= {0,1,2,3,4,5}; Arranger arranger = new Arranger(arr1,arr1.length); int idx=0; for (List<Integer> line : arranger.getResults()) { int third=line.get(2); if(third!=5) { continue; }else { StringBuilder sb=new StringBuilder(); sb.append(names[line.get(0)]); sb.append(names[line.get(1)]); sb.append(names[line.get(2)]); sb.append(names[line.get(3)]); sb.append(names[line.get(4)]); sb.append(names[line.get(5)]); String str=sb.toString(); if(str.contains("射御") || str.contains("御射")) { idx++; System.out.println(idx+"."+str); } } } } }
全排列辅助类代码:
package test240809; 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); }*/ } }
【代码输出结果】
1.礼乐数射御书 2.礼乐数御射书 3.礼乐数书射御 4.礼乐数书御射 5.礼书数乐射御 6.礼书数乐御射 7.礼书数射御乐 8.礼书数御射乐 9.乐礼数射御书 10.乐礼数御射书 11.乐礼数书射御 12.乐礼数书御射 13.乐书数礼射御 14.乐书数礼御射 15.乐书数射御礼 16.乐书数御射礼 17.射御数礼乐书 18.射御数礼书乐 19.射御数乐礼书 20.射御数乐书礼 21.射御数书礼乐 22.射御数书乐礼 23.御射数礼乐书 24.御射数礼书乐 25.御射数乐礼书 26.御射数乐书礼 27.御射数书礼乐 28.御射数书乐礼 29.书礼数乐射御 30.书礼数乐御射 31.书礼数射御乐 32.书礼数御射乐 33.书乐数礼射御 34.书乐数礼御射 35.书乐数射御礼 36.书乐数御射礼
【结论】
程序和数学解法可以相互印证。
END