结对作业二

1.结对成员

  • 李嘉群 061500513
  • 刘双玉 031502424

2.Github链接

gitbub链接地址

3.数据生成

数据输入链接
数据生成程序的原理考虑的因素:

  • 预先构造时间与标签字符串数组:
    • 时间:一周七天,一天6段8:00~10:00 10:00~12:00 14:00~16:00 16:00~18:00 18:00~20:00 20:00~22:00共分为42个时间片
    • 标签:多组标签,选取可能有联系标签放入同一组,保证每组内标签不会互斥,比如,积极与消极在一组。
  • 学生(意愿,时间,标签无重复)
    • 学号:按6个班级,每班50人,从031502101到031502650
    • 部门意愿:0~5 随机从部门编号中选取
    • 空闲时间:10~14 随机从42个时间片中选取10~14个
    • 标签:2~5 同组内选取
  • 部门(时间,标签无重复)
    • 编号:D001到D020
    • 纳新人数:10~15随机
    • 常规活动时间:23,考虑不会在短时间内有多次活动,选取时间有12天的间隔
    • 标签:2~3 同组内选取

4.建模及匹配算法

(1)建模

处理过程分为输入数据处理(Input), 匹配(Match),匹配结果输出(Output)

  • 输入处理模型:

    • dealInput()函数:处理json格式的数据
    • dealDepartments()函数:将处理好的部门数据放入创建好的部门数组中
    • dealStudents()函数:将处理好的学生数据放入创建好的学生数组中
  • 输出处理模型:

    • getAdmitted()函数:获取被录取的学生学号和相应的部门号
    • getUnluckyDepartment()函数:获取没有学生选取的部门号
    • getUnluckStudent()函数:获取没有被部门录取的学生学号

将学生与部门抽象成类

  • 学生
    • 学号(String no)
    • 兴趣标签(String[] tags)
    • 所选的部门(String[] departments)
    • 空闲时间(String[] freeTime)
    • 处理后的空闲时间(int[][] dateTime)(将字符串转换为数字)
    • 被录取的次数(int numAdmit)
  • 部门
    • 部门编号(String no)
    • 限制人数(int memberLimit)
    • 部门标签(String[] tags)
    • 部门活动时间(String[] eventSchedules)
    • 处理后的活动时间(int[][] dateTime)
    • 剩余名额(int numRemaining)

(2)匹配算法的实现

考虑因素(重要性从高到低)

  • 学生志愿优先级:第一志愿优先,其次第二,依此类推
  • 学生空余时间和部门活动时间冲突:因为学生请假超六次会被淘汰,所以时间冲突匹配是没有余地的,时间冲突,部门就不录取。
  • 学生已经被录取次数:录取次数少的同学优先。
  • 学生与部门兴趣标签匹配度:兴趣标签匹配度高的同学优先

算法思想

具体说明

  • 排序规则:学生权值 = 0.3 * (匹配标签个数/学生总标签个数) + 1 / (被录取次数 + 1),除以总标签个数是消除学生填报过多标签带来的优势,乘以0.3是因为,录取次数少带来的优势数值最大为1,标签匹配度也可能为1,乘以0.3再次削弱影响。
  • 更新学生空闲时间:从学生空闲时间中将当前录取部门例会时间去除 。

5.代码规范

(1)代码规范:

命名:类名每个单词首字母大写,方法名首字母小写,其余单词首字母大写,常量名全大写,下划线分格,变量名第一个单词的首字母小写,其后单词的首字母大写。变量名不应以下划线或美元符号开头。

缩进:eclipse切换到下一行时自动产生。

分行:每个语句占用一行,比较清晰。

注释:简单的程序没注释,复杂的程序注释放在相应语句的上方。相应变量的注释放到右边。

(2)代码示例:

	private void matchProcess(int index) {
		
		//将报名情况填入Map
		for(int j = 0; j < Input.stu.length; j++) {
			//如果此轮志愿不为空
    		if(Input.stu[j].getDeptments().length > index) {
    			//取得学号与部门编号,如果二者时间不冲突,则加入map
    			String dept = Input.stu[j].getDeptments()[index];
	    	    String no = Input.stu[j].getNo();

	    	    if(isFreeTimeConflict(j,dept) == true){
	    			map.get(dept).add(no);
	    	    }
    		}
    		
    	} 
		
		//对时间不冲突的学生与部门,第二次筛选
		for(int i = 0; i < Input.depa.length; i++) {
			
			String dno = Input.depa[i].getNo();
			ArrayList<String> tmp = map.get(dno);//报名学生学号List
			int num = Input.depa[i].getNumRemaining();//部门剩余名额
			
			//如果部门还可以录取
			if(num > 0) {
				
				/*
				 * 如果部门剩余名额小于报名人数,根据优先级排序,只取出前num个学生,全部录取
				 * 参数为:部门下标,学生学号List,部门剩余名额
				 */
			    tmp = filter(i,tmp,num);
			    result.get(dno).addAll(tmp);
			    
			    //对部门剩余名额,学生录取个数,学生空闲时间进行更新
				int newNum = num - tmp.size();
				Input.depa[i].setNumRemaining(newNum);
				updateStuStatus(i, tmp);
				
			}
			
		}
	
    }

6.结果评估

理想结果:
时间冲突的学生与部门一定不匹配,对于学生:不如意值(学生不冲突志愿个数 - 被录取次数)应该尽可能平均。对于部门:录取人数在不冲突志愿与部门录取上限取较小一个。

对测试数据的思考:如果数据太小,部门不冲突志愿申请总数小于部门人数限制,测试无意义,如果数据太大,一轮志愿部门就招满人了,测试也没有意义。

测试结果:为了计算方便,去除时间冲突,将部门例会时间设为无,每个志愿均有效,然后控制前150个学生标签匹配度为1,后150个学生标签匹配度为0.最后得出不如意值方差为1.6764888888888967。觉得可以了,其他复杂数据暂时不想测试。(溜了,溜了

7.结对感受

要先吐槽一下队友:放假就无情的抛弃了我,去玩了,我一直深深以为,不靠谱的只有我一个,没想到队友比我心还大,三号都没找我交流一下作业消息,反倒是K班一个13号交作业的人丧心病狂的天天催我。然后是向队友道歉,在选择语言的时候,没有选择双方都会的语言,然后作业后期很焦躁,乱发脾气。在最后快提交作业,转成.exe程序的时候,满脑子就想甩锅走人,也的确这样做了,但是走一会儿还是回来了,然后再走。

题外话:做事情还是要早开始,不能拖,拖着拖着就没有了斗志,“快到死线效率高”是“快到死线要求低”产生的错觉。

原文地址:https://www.cnblogs.com/liu424/p/7642993.html