结对第二次作业

一、结对成员

赖晓连 031502118
林巧娜 031502125

二、github链接

github链接点这里

三、数据模型

认为最好的一组数据:https://github.com/laixiaolian/SoftWare/blob/master/club/clubProject/import.txt

数据生成原理
  • 输入n和m,代表n个部门和m个学生,部门编号从1-n,学生编号从1-m;
  • 随机生成部门的所需学生人数上限,范围为[0,15],
  • 定义了十个标签:"programming","reading","film","music","dance","chess","handwriting","photograph","sports" ,"painting" ,从中随机选四个作为部门标签,选三个作为学生标签;
  • 部门活动时间段:在实际生活中,每个部门的常规活动时间都是一周一次,所以我们从周一到周天,时间在7:00-23:00之间任选一天以及其中的一个小时作为该部门的常规活动时间;
  • 学生空闲时间段:任选周一到周天五个天数(可重复),时间在7:00-23:00任意长度时间段,不可出现同一天的连续时间段分为两次出现的情况;
  • 学生志愿为5栏,从1-n个部门编号中挑选5个,考虑到实际情况,很多学生不一定对那么多部门感兴趣,只想加入少数部门,所以志愿可重复。
  • 学生绩点:生成1.00-5.00之间任意数,小数点保留两位。

四、代码

生成部门数据

void department::DepartmentData(int n, int m)
{
	srand((unsigned)time(NULL));//随机化种子

	for (int i = 0; i < n; i++)
	{
		depart[i].DepartmentNo = i + 1;//部门编号
		depart[i].MemberLimit = (rand() % 15) + 1;//每个部门的限定人数
												  //部门特点标签,每个部门4个
		int count[9] = { 0 };
		for (int j = 0; j < 4;)
		{
			int k = rand() % 9 + 1;
			//解决部门特点标签重复问题
			if (count[k] == 0)
			{
				count[k] = 1;
				depart[i].DepartmentTags[j] = TotalTags[k];
				j++;
			}

		}
	}
	for (int i = 0; i < n; i++)
	{
		//cout << "部门编号:" << depart[i].DepartmentNo << "  部门限定人数:" << depart[i].MemberLimit << endl;
		cout << depart[i].DepartmentNo << " " << depart[i].MemberLimit << endl;
		//cout << "部门特点:";

		for (int j = 0; j < 4; j++)
		{
			cout << depart[i].DepartmentTags[j] << "  ";
		}
		cout << endl;
		//cout << "部门常规活动时间段:";
		int day = rand() % 7;
		cout << week[day] << " ";
		int hour1 = rand() % (15 + 1) + 7; //生成空余时间范围为7:00-22:00
		int hour2 = hour1 + 1;

		//int型转换为字符串,方便后面时间的表示
		string str1 = std::to_string(hour2);
		string str2 = std::to_string(hour1);
		depart[i].Schedules = str2 + " :00- " + str1 + " :00";
		cout << depart[i].Schedules << endl;
	}
}

因为之前的作业有说到学生参加部门不能请假超过五次,所以我们觉得一个学生要是时间和部门常规时间不符合,那就不在考虑这位学生。因此我们是在时间已经符合的条件下,考虑志愿优先。
而计算学生志愿的权重,首先考虑的是学生空余时间和部门常规时间是否匹配,没有匹配的学生加入该部门就没有意义了,只有匹配了才可以计算权重,参与到之后的选择中。对于权重中绩点和标签所占的比重,我们尝试过替换成其他的值,但是中选人数都很随机,不能直观的判断哪个更好,所以我们选择了一个比较好计算的比例。而计算权重时加入tidu是为了起到志愿优先的作用,不管你的成绩如何,只要你是优先选择该志愿的,那么你就会有更大的机会被选到。

for (int j = 0; j < m; j++)
{
	
	for (int k = 0; k < 5; k++)
	{
		//只有当学生时间与常规时间不冲突的时候才计算该志愿的权重
		if (StuRank[st[j].StudentNo][st[j].aspiration[k]] == 1)
		{
			for (int f = 0; f < 3; f++)
			{
				for (int o = 0; o < 4; o++)
				{
					if ((q[st[j].aspiration[k]] != 1) && (st[j].StudentTags[f]
						== dep[st[j].aspiration[k] - 1].DepartmentTags[o]))
					{
						num+=1;
					}
				}
			}

			if ((q[st[j].aspiration[k]] != 1))//第一次出现这个志愿
			{
				//志愿权重,梯度用来表示这个志愿是该学生的第几志愿,5K是第一志愿,4K是第二志愿,依次类推
				StuRank[st[j].StudentNo][st[j].aspiration[k]] = (int)((st[j].Point*0.14 + num * 0.1 + tidu) * 1000);
				
				q[st[j].aspiration[k]] = 1;//将已经选择的部门编号置为1
			}
			num = 0;
		}
		tidu -= 1;//志愿梯度,第一志愿的梯度最大,之后逐级递减
	}
	for (int i = 1; i <= n; i++)
	{
		q[i] = 0;
	}
	memset(q, 0, sizeof(q));
	tidu = 5;
}

对选择同一志愿的学生根据权重从大到小排序,部门选择时将根据权重选择

void Function::sort()
{
	/*for (int i = 0; i < m; i++)
	{
		cout << "编号:" << i + 1 << endl;
		for (int j = 0; j < 5; j++)
		{
			cout << "志愿 " << st[i].aspiration[j] << " 的分数为:" << StuRank[st[i].StudentNo][st[i].aspiration[j]] << endl;
		}
	}*/
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (StuRank[st[j].StudentNo][i + 1] != 0)
			{
				temp[i + 1][k[i + 1]] = st[j].StudentNo;//k[i+1]表示选了部门i+1的人一共有多少
				k[i + 1]++;
			}
		}
	}
	for (int i = 0; i < n; i++)//i+1是部门编号
	{
		memset(s, 0, sizeof(s));
		//将所有同学的该志愿权重存入一维数组
		for (int j = 0; j < k[i + 1]; j++)
		{
			s[j] = StuRank[temp[i + 1][j]][i + 1];
		}
		for (int j = 0; j < k[i + 1] - 1; j++)//冒泡排序,按照权重从大到小排序
		{
			for (int p = 0; p < k[i + 1] - j - 1; p++)
			{
				if (s[p] <s[p + 1])
				{
					int t;
					int t1;

					//权重和学生编号同时替换
					t1 = s[p];
					s[p] = s[p + 1];
					s[p + 1] = t1;

					t = temp[i + 1][p]; //学生编号
					temp[i + 1][p] = temp[i + 1][p + 1];
					temp[i + 1][p + 1] = t;

				}
			}
		}
	}
}

五、代码规范

1、使用驼峰式命名方法

    int DepartmentNo; //部门编号
	int MemberLimit;//学生数上限
	string DepartmentTags[20]; //特点标签,两个以上
	string Schedules;//常规活动时间段

2、每个功能封装成函数。

六、结果分析评价

时间符合的条件下考虑志愿优先:

优先条件 学生总数 部门招收人数 匹配学生个数 未匹配学生个数 实际耗时(s) 输出文件路径
志愿优先 300 183 136 164 0.998s output.txt

七、结对感受

laixl:这是第一次以结对编程的方式完成作业,感觉很神奇,感触也蛮多的。两个人编程和自己编程还是有很大差别的,在这次编程过程中,两个人的想法时常会撞出火花。而且两个人一起编程的时候有一些小的细节,小的错误,小伙伴也会立刻指出来,节省了很多时间。总之,这是一次奇妙的体验!
reset-:本次的作业的完成时间正好是在国庆节,两个人不在一起,交流只通过网络就没有那么方便,虽然过程很无奈,但是在每次能够成功实现一块内容的时候激动心情也是加倍的。通过这次的结对编程作业,真正的体验了两人合作的编程感觉,可以互相讨论到底是什么地方出现了问题,一步步改正,也可以督促自己不要懒惰,遇到不会的及时询问,及时查资料,不会想着说先歇一会再来。

原文地址:https://www.cnblogs.com/laixiaolian/p/7643724.html