【java/算法/组合】某校开设A类选修课3门,B类选修课4门,某同学从中共选3门。学校要求一类至少选一门,问不同选法有几种并请列举出具体选法。

【题干】

某校开设A类选修课3门,B类选修课4门,某同学从中共选3门。学校要求一类至少选一门,问不同选法有几种。

【数学解法】

只有两种情况:A类选一门B类选两门  和 A类选两门B类选一门

类别一:A类选一门B类选两门,C31*C42;(C31表示3中选1,以下类同)

类别二:A类选两门B类选一门,C32*C41;

总数Sum=C31*C42+C32*C41=3*4*3/2/1+3*2/2/1*4=18+12=30种

【代码解法】

做两个M选N的选择器,然后让结果一一配对。

选择器代码:

package test230422;

import java.util.List;

public class CourseSelector {
    public static void main(String[] args) {
        int idx=0;// 序号
        
        String[] coursesA= {"孔孟哲学","老庄思想","法家规制"};
        String[] coursesB= {"鲍鹏山讲水浒","吴闲云谈西游","王立群聊三国","刘心武扯红楼"};

        for(int i=1;i<3;i++) {
            int aCnt=i;
            Combiner selectedA=new Combiner(coursesA,aCnt);
            List<List<String>> resultsA=selectedA.getResults();
            
            int bCnt=3-i;
            Combiner selectedB=new Combiner(coursesB,bCnt);
            List<List<String>> resultsB=selectedB.getResults();
            
            
            for(List<String> resA:resultsA) {
                for(List<String> resB:resultsB) {
                    System.out.println(String.format("%02d", ++idx) +"."+resA+","+resB);
                }
            }
        }
    }
}

组合器代码:

package test230422;

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

/**
 * 从数组中选择有限个数的组合器
 * 比如从abc中选2个,会产生ab,ac,bc的结果
 */
public class Combiner {
    /**
     * 选择的结果
     */
    private List<List<String>> results;
    
    /**
     * 构造函数
     * @param candidates 候选者名单
     * @param selectCnt 选择的数量
     */
    public Combiner(String[] candidates,int selectCnt) {
        int nCnt = candidates.length;
        
        if(selectCnt>nCnt) {
            throw new ArrayIndexOutOfBoundsException(selectCnt+">"+nCnt);
        }
        
        results=new ArrayList<>();

        int nBit = (0xFFFFFFFF >>> (32 - nCnt));

        for (int i = 1; i <= nBit; i++) {
            List<String> ls=new ArrayList<>();
            
            for (int j = 0; j < nCnt; j++) {
                if ((i << (31 - j)) >> 31 == -1) {
                    ls.add(candidates[j]);
                }
            }

            if(ls.size()==selectCnt) {
                results.add(ls);
            }
        }
    }
    
    /**
     * 取得选择的结果
     * @return
     */
    public List<List<String>> getResults(){
        return results;
    }
    
    /**
     * 使用示例
     * @param args
     */
    public static void main(String[] args) {
        String[] arr= {"A","B","C"};
        Combiner c=new Combiner(arr,2);
        
        List<List<String>> results=c.getResults();
        for(List<String> ls:results) {
            System.out.println(ls);
        }
    }
}

 【运行结果】

 

01.[孔孟哲学],[鲍鹏山讲水浒, 吴闲云谈西游]
02.[孔孟哲学],[鲍鹏山讲水浒, 王立群聊三国]
03.[孔孟哲学],[吴闲云谈西游, 王立群聊三国]
04.[孔孟哲学],[鲍鹏山讲水浒, 刘心武扯红楼]
05.[孔孟哲学],[吴闲云谈西游, 刘心武扯红楼]
06.[孔孟哲学],[王立群聊三国, 刘心武扯红楼]
07.[老庄思想],[鲍鹏山讲水浒, 吴闲云谈西游]
08.[老庄思想],[鲍鹏山讲水浒, 王立群聊三国]
09.[老庄思想],[吴闲云谈西游, 王立群聊三国]
10.[老庄思想],[鲍鹏山讲水浒, 刘心武扯红楼]
11.[老庄思想],[吴闲云谈西游, 刘心武扯红楼]
12.[老庄思想],[王立群聊三国, 刘心武扯红楼]
13.[法家规制],[鲍鹏山讲水浒, 吴闲云谈西游]
14.[法家规制],[鲍鹏山讲水浒, 王立群聊三国]
15.[法家规制],[吴闲云谈西游, 王立群聊三国]
16.[法家规制],[鲍鹏山讲水浒, 刘心武扯红楼]
17.[法家规制],[吴闲云谈西游, 刘心武扯红楼]
18.[法家规制],[王立群聊三国, 刘心武扯红楼]
19.[孔孟哲学, 老庄思想],[鲍鹏山讲水浒]
20.[孔孟哲学, 老庄思想],[吴闲云谈西游]
21.[孔孟哲学, 老庄思想],[王立群聊三国]
22.[孔孟哲学, 老庄思想],[刘心武扯红楼]
23.[孔孟哲学, 法家规制],[鲍鹏山讲水浒]
24.[孔孟哲学, 法家规制],[吴闲云谈西游]
25.[孔孟哲学, 法家规制],[王立群聊三国]
26.[孔孟哲学, 法家规制],[刘心武扯红楼]
27.[老庄思想, 法家规制],[鲍鹏山讲水浒]
28.[老庄思想, 法家规制],[吴闲云谈西游]
29.[老庄思想, 法家规制],[王立群聊三国]
30.[老庄思想, 法家规制],[刘心武扯红楼]

数学解答和程序输出可以相互验证。

END

 

posted @ 2023-04-22 04:36  逆火狂飙  阅读(53)  评论(0编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东