PAT A1080 Graduate Admission 简单思路

题目链接
这道题相对于之前的排序题来说,确实有点难。《算法笔记》上给的解法非常有效,但是变量有点多,很容易搞混。

书上的参考代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
struct Stu{
	int GE, GI, sum;
	int r,stuID;
	int cho[6];
}stu[40010];
struct Sch{
	int quota;
	int stuNum;
	int id[40010];
	int lastAdmit;
}sch[110];
bool cmpStu(Stu a, Stu b){
	if (a.sum!=b.sum) return a.sum>b.sum;
	else return a.GE>b.GE;
} 
bool cmpID(int a, int b){
	return stu[a].stuID<stu[b].stuID;
}
int main(){
	int n,m,k;
	scanf("%d%d%d",&n,&m,&k);
	for (int i=0; i<m; i++){
		scanf("%d",&sch[i].quota);
		sch[i].stuNum=0;
		sch[i].lastAdmit=-1;
	}
	for (int i=0; i<n; i++){
		stu[i].stuID=i;
		scanf("%d%d",&stu[i].GE,&stu[i].GI);
		stu[i].sum=stu[i].GE+stu[i].GI;
		for (int j=0; j<k; j++){
			scanf("%d",&stu[i].cho[j]);
		}
	}
	sort(stu,stu+n,cmpStu);
	for (int i=0; i<n; i++){
		if (i>0 && stu[i].sum==stu[i-1].sum && stu[i].GE==stu[i-1].GE){
			stu[i].r=stu[i-1].r;
		}else {
			stu[i].r=i;
		}
	}
	for (int i=0; i<n; i++){
		for (int j=0; j<k; j++){
			int choice=stu[i].cho[j];
			int num=sch[choice].stuNum; 
			int last=sch[choice].lastAdmit;
			if (num<sch[choice].quota || (last!=-1 && stu[i].r==stu[last].r)){
				sch[choice].id[num]=i;
				sch[choice].lastAdmit=i;
				sch[choice].stuNum++;
				break;
			} 
		}
	}
	for (int i=0; i<m; i++){
		if (sch[i].stuNum>0){
			sort(sch[i].id, sch[i].id+sch[i].stuNum, cmpID);
			for (int j=0; j<sch[i].stuNum; j++){
				printf("%d",stu[sch[i].id[j]].stuID);
				if (j<sch[i].stuNum-1){
					printf(" ");
				}
			}
		}
		printf("\n");
	}
}

总的来看思路很明确,但是也很容易出错,变量过多导致关系有点复杂,但是关于比较函数那一段还是值得学习的。

如果少用一些全局变量,多用一些临时变量,那么变量之间的关系就会简单很多,小白也不至于看得云里雾里,我的代码:

#include <cstdio>
#include <algorithm>
using namespace std;
struct Stu{
	int ge,gi,final;
	int pre[10];
	int rank,id;
	int isAdmitted;
	int admitSch;
}stu[40010];
bool cmp(Stu a, Stu b){
	if (a.final!=b.final) return a.final>b.final;
	else return a.ge>b.ge;
}
int main(){
	int n,m,k;
	scanf("%d %d %d",&n, &m, &k);
	int sch[110];
	for (int i=0; i<m; i++){
		scanf("%d",&sch[i]);
	}
	for (int i=0; i<n; i++){
		stu[i].id=i;
		stu[i].isAdmitted=0;
		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].pre[j]);
		}
	}
	sort(stu,stu+n,cmp);
	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;	
		}
	}
	int isExceeded[10]={0};
	for (int i=0; i<n; i++){
		stu[i].admitSch=-1;
		for (int j=0; j<k; j++){
			if (!stu[i].isAdmitted && !isExceeded[stu[i].pre[j]]){
				stu[i].isAdmitted=1;
				sch[stu[i].pre[j]]--;
				stu[i].admitSch=stu[i].pre[j];
				if (sch[stu[i].pre[j]]>0 || stu[i+1].rank==stu[i].rank){
					isExceeded[stu[i].pre[j]]=0;
				}else isExceeded[stu[i].pre[j]]=1;
				break;
			}
		}
	}
	for (int i=0; i<m; i++){
		int count=0;
		int admit[40010];
		for (int j=0; j<n; j++){
			if (stu[j].admitSch==i) {
				admit[count++]=stu[j].id;
			}
		}
		sort(admit,admit+count);
		for (int p=0; p<count; p++){
			if (!p) printf("%d",admit[p]);
			else printf(" %d",admit[p]);
		}
		printf("\n");
	}
}

两个代码在输出部分,有很大区别, 之前的部分思路很相似,只是我的代码没有用学校这个结构体。我的代码的漏洞是,如果这几个院校不准备录取学生, 那么代码输出就是错误的, 但是实际情况下, 如果一个学校在报考名单中, 他不可能预录取的配额是0, 否则就是欺骗考生。测试点的数据也是比较正常的的数据, 是贴合实际的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值