这道题很简单,但是做了很久。这里想贴两个版本,第一个是不完全正确的,但是仍然想保留下来提醒自己注意留意容易忽略的小细节!
总结一下出错的地方,首先是要注意保留学生id,然后要注意在录取环节千万不要把循环变量i当做学生id。个人感觉保存学生rank比保存未排序的stu要好,不容易出错。
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
#define MAXN 40000
#define MAXM 100
struct Stu{
int id;//记录学生最初编号
int ge;
int gi;
int final;
int choice[6];
bool operator <(const Stu &b) const{
if(final!=b.final)
return final>b.final;
else
return ge>b.ge;
}
}stu[MAXN];
struct School{
vector<int> stu;
int quota;
}sch[MAXM];
int main(){
int n,m,k;
//freopen("/Users/pantingting/Documents/code/data/input", "r", stdin);
scanf("%d%d%d",&n,&m,&k);
for (int i=0; i<m; i++) {
scanf("%d",&sch[i].quota);//读取每个学校的指标
}
for (int i=0; i<n; i++) {//读取学生成绩并排序
scanf("%d%d",&stu[i].ge,&stu[i].gi);
stu[i].final=(stu[i].ge+stu[i].gi);
for (int j=0; j<k; j++) {//读取学生志愿
scanf("%d",&stu[i].choice[j]);
}
stu[i].id=i;//记录学生的初始编号
}
sort(stu, stu+n);
for (int i=0; i<n; i++) {//i为学生排序后的编号,j为学生i的志愿编号
for (int j=0; j<k; j++) {//按照志愿顺序检查学校是否已经招满。
int schid=stu[i].choice[j];
if (sch[schid].quota==0) {//若该校招生指标为0则略过
continue;
}
if (sch[schid].stu.size()<sch[schid].quota) //该校未招满,则收录该生
{
sch[schid].stu.push_back(stu[i].id);//记录的是学生原来的id,而不是排序后的
break;
}
else//该校已经招满了,或者chao额了,必须录取所有同rank的学生。
{
int last=sch[schid].stu[sch[schid].stu.size()-1];//取出最后一名学生的编号,这个编号是实际号
if(stu[last].final==stu[i].final&&stu[last].ge==stu[i].ge)//若为tie则可以超额录取
{
sch[schid].stu.push_back(stu[i].id);
break;
}
}
}
}
for (int i=0; i<m; i++) {
if (sch[i].stu.size()==0) {//若该校无学生则输出空行、
printf("\n");
}
else
sort(sch[i].stu.begin(), sch[i].stu.end());//对结果进行排序
for (int j=0; j<sch[i].stu.size(); j++) {
printf("%d",sch[i].stu[j]);
if (j!=sch[i].stu.size()-1) {
printf(" ");//最后一个id后面不能有空格
}
else
printf("\n");
}
}
return 0;
}
修改后的代码(通过全部case)
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
#define MAXN 40000
#define MAXM 100
struct Stu{
int id;//记录学生最初编号
int ge;
int gi;
int final;
int choice[6];
int rank;
bool operator <(const Stu &b) const{
if(final!=b.final)
return final>b.final;
else
return ge>b.ge;
}
}stu[MAXN];
struct School{
vector<int> stu;
int quota;
int lastrank;//记录该校最后一名学生的rank;
}sch[MAXM];
int main(){
int n,m,k;
// freopen("/Users/pantingting/Documents/code/data/input", "r", stdin);
scanf("%d%d%d",&n,&m,&k);
for (int i=0; i<m; i++) {
scanf("%d",&sch[i].quota);//读取每个学校的指标
}
for (int i=0; i<n; i++) {//读取学生成绩并排序
scanf("%d%d",&stu[i].ge,&stu[i].gi);
stu[i].final=(stu[i].ge+stu[i].gi);
for (int j=0; j<k; j++) {//读取学生志愿
scanf("%d",&stu[i].choice[j]);
}
stu[i].id=i;//记录学生的初始编号
}
sort(stu, stu+n);
stu[0].rank=0;//给每个学生计算排名
for (int i=1; i<n; i++) {
if (stu[i].final==stu[i-1].final&&stu[i].ge==stu[i-1].ge) {
stu[i].rank=stu[i-1].rank;
}
else
stu[i].rank=i;
}
for (int i=0; i<n; i++) {//i为学生排序后的编号,j为学生i的志愿编号
for (int j=0; j<k; j++) {//按照志愿顺序检查学校是否已经招满。
int schid=stu[i].choice[j];
if (sch[schid].quota==0) {//若该校招生指标为0则略过
continue;
}
if (sch[schid].stu.size()<sch[schid].quota) //该校未招满,则收录该生
{
sch[schid].stu.push_back(stu[i].id);//记录的是学生原来的id,而不是排序后的
sch[schid].lastrank=stu[i].rank;
break;
}
else//该校已经招满了,或者chao额了,必须录取所有同rank的学生。
{
/*int last=sch[schid].stu[sch[schid].stu.size()-1];//取出最后一名学生的编号,这个编号是实际编号,若想取得该生的成绩,应该从原来未排序的stu中取得。
if(stu[last].final==stu[i].final&&stu[last].ge==stu[i].ge)//若为tie则可以超额录取
{
sch[schid].stu.push_back(stu[i].id);
break;
}*/
if (sch[schid].lastrank==stu[i].rank) {
sch[schid].stu.push_back(stu[i].id);
break;
}
}
}
}
for (int i=0; i<m; i++) {
if (sch[i].stu.size()==0) {
printf("\n");
}
else
sort(sch[i].stu.begin(), sch[i].stu.end());//对结果进行排序
for (int j=0; j<sch[i].stu.size(); j++) {
printf("%d",sch[i].stu[j]);
if (j!=sch[i].stu.size()-1) {
printf(" ");//最后一个id后面不能有空格
}
else
printf("\n");
}
}
return 0;
}