1080 Graduate Admission (30分)
思路
思路的话 我的方向是学生挑学校
学生成绩排好序之后 优秀的学生先挑学校 到后面的学生的时候 有的学校已经录满了 那就换第二志愿、第三志愿、依次下去 直到录取结束
第一次的代码(只拿了24分 不知道哪错了)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
struct student
{
int id; //序号
int bishi;//笔试成绩
int mianshi;//面试成绩
int choice[10];//喜欢的学校
int score;//最终分数
int rank;//排名
int admitted;//录取的学校
int lastone ;
}stu[40100];
bool cmp(student a, student b)
{
if (a.score == b.score) return a.bishi > b.bishi;
else return a.score > b.score;
}
int n, m, k;
bool Rank(student a, int x)
{
student b;
for (int i = 0;i < n;i++) //找到喜欢学校已招的最后一名
{
if (stu[i].admitted == a.choice[x] && stu[i].lastone == 1)
{
b = stu[i];
}
}
if (a.rank == b.rank) //如果和喜欢学校已招的最后一名排名一样的话 那就录取
{
return true;
}
else
{
return false;
}
}
int main()
{
int school[1100] = { 0 };//每个学校已经招的人
int quota[1100]; //每个学校的名额
cin >> n >> m >> k;
for (int i = 0;i < m;i++)
{
cin >> quota[i];
//每个学校的名额
}
for (int i = 0;i < n;i++)
{
stu[i].id = i;
memset(stu[i].choice,-1,sizeof(stu[i].choice));
stu[i].admitted=-1;
stu[i].lastone=0;
cin >> stu[i].bishi >> stu[i].mianshi;
stu[i].score = stu[i].bishi + stu[i].mianshi;
for (int j = 0;j < k;j++)
{
cin >> stu[i].choice[j];
}
}
sort(stu, stu + n, cmp);
//排名
stu[0].rank = 1;
for (int i = 1;i < n;i++)
{
if (stu[i].score == stu[i - 1].score && stu[i].bishi == stu[i - 1].bishi)
{
stu[i].rank = stu[i - 1].rank;
}
else
{
stu[i].rank = i + 1;
}
}
//排好序 学生开始挑学校
for (int i = 0;i < n;i++)
{
int j;
for (j = 0;j < k;j++)
{
if (school[stu[i].choice[j]] < quota[stu[i].choice[j]])//如果喜欢的学校没满 就直接进去
{
if (school[stu[i].choice[j]] == quota[stu[i].choice[j]] - 1)
{
stu[i].lastone = 1;
}
school[stu[i].choice[j]]++; //学校已招人数+1
stu[i].admitted = stu[i].choice[j];//学生录取学校确定
break;
}
else if (school[stu[i].choice[j]] == quota[stu[i].choice[j]] && Rank(stu[i], stu[i].choice[j]) == true)//如果学校已经招满了 但是和招满学校的最后一名排名一样 扩招
{
school[stu[i].choice[j]]++; //学校已招人数+1
stu[i].admitted = stu[i].choice[j];//学生录取学校确定
break;
}
else
{
continue;
}
}
if (j == k)
{
stu[i].admitted = -1; //这个学生没录到
}
}
//录取结束
int shuchu[1100][1100]; //为了能够从小到大输出 搞一个二维数组输出
memset(shuchu, -1, sizeof(shuchu)); // 全部赋值为-1
for (int i = 0;i < m;i++)
{
for (int j = 0;j < n;j++)
{
if (stu[j].admitted != -1) //如果不为-1 即被录取了
{
shuchu[stu[j].admitted][stu[j].id] = stu[j].id; //shuchu【录取学校】【id】=id;
}
}
}
for (int i = 0;i < m;i++)
{
int flag = 0; //为了方便输出的空格
for (int j = 0;j < n;j++)
{
if (shuchu[i][j] != -1 && flag == 0) //第一个只输出第一个数
{
cout << shuchu[i][j];
flag = 1;
}
else if (shuchu[i][j] != -1 && flag == 1) //后面的输出空格+输出的数
{
cout << " " << shuchu[i][j];
}
}
cout << endl; //换行
}
return 0;
}
换了方法后的代码(30分)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
struct student
{
int id;
int bishi, mianshi, sum;
int rank;
int num;
int choice[6] = { -1,-1,-1,-1,-1,-1 };
}stu[40010];
struct school
{
int lastone;
int quota;
int num;
int id[40010];
}s[110];
bool cmp(student a , student b)
{
if (a.sum == b.sum) return a.bishi > b.bishi;
else return a.sum > b.sum;
}
int main()
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 0;i < m;i++)
{
cin >> s[i].quota;
s[i].num = 0;
s[i].lastone = -1;
memset(s[i].id, -1, sizeof(s[i].id));
}
for (int i = 0;i < n;i++)
{
stu[i].id = i;
cin >> stu[i].bishi >> stu[i].mianshi;
stu[i].sum = stu[i].bishi + stu[i].mianshi;
for (int j = 0;j < k;j++)
{
cin >> stu[i].choice[j];
}
}
sort(stu, stu + n, cmp);
for (int i = 0;i < n;i++)
{
stu[i].num = i; //num对应的是排序完之后的顺序 此处是为了方便找到录取学校的最后一名
}
stu[0].rank = 1;
for (int i = 1;i < n;i++)
{
if (stu[i].sum == stu[i - 1].sum && stu[i].bishi == stu[i - 1].bishi)
{
stu[i].rank = stu[i - 1].rank;
}
else
{
stu[i].rank = i + 1;
}
}
//开始录取
for (int i = 0;i < n;i++)
{
for (int j = 0;j < k;j++)
{
if (s[stu[i].choice[j]].num < s[stu[i].choice[j]].quota) //没招满
{
if (s[stu[i].choice[j]].num == s[stu[i].choice[j]].quota - 1) //如果是最后一个录取的
{
s[stu[i].choice[j]].lastone = stu[i].num; //一定要是num 因为接下来是stu[s[stu[i].choice[j]].lastone].rank 这里需要的是排序后的序列 而不是ID
}
s[stu[i].choice[j]].id[stu[i].id] = stu[i].id;
s[stu[i].choice[j]].num++;
break;
}
else if (stu[i].rank == stu[s[stu[i].choice[j]].lastone].rank && s[stu[i].choice[j]].num >= s[stu[i].choice[j]].quota)
{
s[stu[i].choice[j]].id[stu[i].id] = stu[i].id;
s[stu[i].choice[j]].num++;
break;
}
else
{
continue;
}
}
}
for (int i = 0;i < m;i++)
{
int flag = 0;
if (s[i].num > 0)
{
for (int j = 0;j < n;j++)
{
if (s[i].id[j] != -1 && flag==0)
{
cout << s[i].id[j];
flag = 1;
}
else if(s[i].id[j] != -1 && flag == 1)
{
cout << " " << s[i].id[j];
}
}
}
cout << endl;
}
return 0;
}
第一次的代码里面 我用了一个结构体数组 然后创建了许多的数组来表示学校的
那一面
然后就发现只能拿24分 运行超时了一个点 可能是在找最后一名学生那里用的循环
太多 所以这种方法有点费时间
于是 第二次我用了两个结构体数组 学生的为一组 学校的为一组 然后就AC啦!
如果有哪位大佬能帮我找一下第一个代码的错误 麻烦告诉我一下 有偿!!!