zoukankan      html  css  js  c++  java
  • 第二次结对编程作业——毕设导师智能匹配

    鲍亮 031402401 李陈辉 031402409


    问题描述:

    编码实现一个毕设导师的智能匹配的程序。提供输入包括:30个老师(包含带学生数的要求的上限,单个数值,在[0,8]内),100个学生(包含绩点信息),每个学生有5个导师志愿(志愿的导师可以重复但不能空缺)。实现一个智能自动分配算法,根据输入信息,输出导师和学生间的匹配信息(一个学生只能有一个确认导师,一个导师可以带少于等于其要求的学生数的学生)及未被分配到学生的导师和未被导师选中的学生。


    问题分析

    该问题的难点在于:学生填写的志愿会偏重于某些导师,导致许多选热门导师的学生最后选不到(由于绩点等原因相对较低),而冷门导师又收不到预期人数的学生。
    为了解决该问题制定以下原则:

    • 保证匹配结果越多学生选到导师越好;
    • 只有选了该导师的学生才有可能成为他的学生;
    • 学生的五个志愿平行,志愿顺序不影响结果;
    • 选择导师的学生数超出导师预期收取的人数时,按绩点高低选取。

    算法设计

    为每位导师设置一个权重值p[i],与导师要求人数n[i],选取此导师的学生数s[i]存在如下关系:

    该式子的意义是,把n-s的值作为导师被选取的第一优先标准,n的值作为第二优先标准(乘以系数0.1表示其比第一优先标准低一个优先级)。
    设置图G[StudentNum][TeacherNum]表示学生选择的导师,初始化如下:i学生选择了j老师,则置G[i][j]=1,否则G[i][j]=0。
    现设计算法如下:

    1. 计算每个导师p值
    2. 选取p值最高的导师i,取出该导师(不再放回),导师总数tn减去1
    3. 若是s[i]=0,转步骤1;否则若p[i]>0转步骤4,若p[i]<=0转步骤5
    4. 对于选择了i的每个学生j,取出该学生(不再放回),输出:该学生为i的学生,若G[j][k]=1(k=0,1,2...TNUM),则G[j][k]=0,s[k]减去1。转步骤6
    5. 选取选择了i的学生中绩点排前n[i]的学生,取出该学生(不再放回),输出:该学生为i的学生,若G[j][k]=1(k=0,1,2...TNUM),则G[j][k]=0,s[k]减去1。
    6. 若tn<0,算法结束;否则转步骤1。

    代码实现

    随机生成以下数据

    void InitGradePoints(vector<double> &g){ //初始随机绩点 
    	for(int i=0;i<SNUM;i++){
    		g.push_back((double)rand()/RAND_MAX*4.0+1.0);
    	}
    }
    
    void InitPeoLimit(vector<int> &p){ //初始随机导师设定人数 
    	for(int i=0;i<TNUM;i++){
    		p.push_back(rand()%8+1);
    	}
    }
    
    void InitZ(int z1[],int z2[],int z3[],int z4[],int z5[]){//初始随机学生志愿 
    	for(int i=0;i<SNUM;i++){
    		z1[i]=rand()%TNUM;
    		z2[i]=rand()%TNUM;
    		z3[i]=rand()%TNUM;
    		z4[i]=rand()%TNUM;
    		z5[i]=rand()%TNUM;
    	}
    }
    

    导师权重初始化

    for(int i=0;i<TNUM;i++){        //计算权重值 
    		t[i]=PeoLimit[i];
    		power[i]+=t[i]*1.1;
    	}
    	for(int i=0;i<SNUM;i++){
    		score[i]=GradePoints[i];
    		choose=Z1[i];
    		g[i][choose]=1;
    		choose=Z2[i];
    		g[i][choose]=1;
    		choose=Z3[i];
    		g[i][choose]=1;
    		choose=Z4[i];
    		g[i][choose]=1;
    		choose=Z5[i];
    		g[i][choose]=1;
    	}
    	for(int i=0;i<SNUM;i++){                //遍历图g,计算权重值 
    		for(int j=0;j<TNUM;j++){
    			if(g[i][j]==1){ 
    				power[j]-=1.0;
    				s[j]+=1;
    			} 
    		}
    	}
    

    每取出一个学生,对图G、各导师权重、学生数更新

    void update(int g[][TNUM],int i,double power[],int s[]){
    	for(int j=0;j<TNUM;j++){
    		if(g[i][j]==1){        
    	 		g[i][j]=0;
    			power[j]+=1.0;    //更新权重 
    			s[j]-=1;          //学生数减少 
    		}
    	}
    }
    
    
    

    ps:输入输出采用文本文件的方式输入


    测试结果

    测试样本为100个学生,30个老师,输入数据随机生成,统计10次实验结果如下

    分析:通过上图可知落选的学生占比极低,为0%至3%,平均是0.7人;而老师落选率则相对较高,最高达23.3%,平均是4.7人,由于这个算法考虑的是使学生尽量选到导师,绩点因素则是次要因素,所以出现以上的情况。


    结对感受:

    yuaoi:两个人结对确实会发生奇妙的化学反应,两个人的思维碰撞产生的火花是一个人独自思考得不到的。我们两个在对算法的讨论中,各抒己见,并对对方的想法的漏洞提出质疑,才使想法不断改进。两个人分工编程考验了我们的合作能力,将两个程序结合是一个痛苦的过程,但在对友的帮助下我找到自己程序的漏洞,最后成功合并了我们的代码。

    Salaka:感觉有了具体的项目做就很明确,在分析问题的时候更有针对性了。和队友讨论分析导师分配问题的时候也探讨了许多的方案,在这个过程中学习到了很多。本来在讨论前期的时候,我们想用很粗略的算法把这个问题解决,后来觉得这样落选的学生就会很多。于是我们讨论了约一个晚上的时间,终于一步一步把这个问题逐渐量化。讨论清楚了以后就开始写代码了,队友解决问题的能力真是神速,我也很配合地完成了自己的部分,所以很开心。


    附源代码链接及测试结果
    https://coding.net/u/Salaka/p/Tutor-distribution/git

  • 相关阅读:
    [bzoj1089] 严格n元树
    [bzoj1097] 旅游景点atr
    [hdu3887] Counting Offspring
    [POJ3321] Apple Tree
    [POJ3635] Full Tank?
    git
    【MySQL】数据的导出导入
    Ubuntu python 开发环境配置
    测试markdown
    约瑟夫环问题-java实现
  • 原文地址:https://www.cnblogs.com/yuaoi/p/5918094.html
Copyright © 2011-2022 走看看