2019-02-26-University Entrace Examination -ZOJ1023-稳定婚姻算法(变式)

ZOJ-1023-University Entrace Examination

Problem Description

There is a fierce competition among high-school graduates in Iran to pass the centralized nationwide university entrance examination. Ministry of Science, Research, and Technology has set up the Education Evaluation Organization (EEO) to take care of all aspects of this big exam. This year the EEO managed to select some 150,000 students to enter universities out of 1.4 million high school graduates participated in a tough 4.5 hours multiple-choice exam. This annual event is usually preceded by a multi-billion Rial business offering preparatory courses to enthusiastic students. A few weeks after the big exam day, each participant receives a score sheet, and a list of Field-Department-University (FDU), displaying each field of study in the universities锟斤拷 departments (e.g., the Software Engineering field of Computer Engineering department at Sharif University of Technology) along with their capacity for that year. The eligible participants (those who have scored enough to be allowed to declare their FDU priorities) fill out a priority indication form, and declare the FDUs they like to enter, in the order of their preference. The EEO processes the forms, and considering the total score, the participant锟斤拷s FDU priority list, and some other selection rules, enters the accepted participants锟斤拷 names in the list of each FDU, until all capacities are exhausted. Those who are not entered in a list are considered failed and may try again next year. Each accepted participant锟斤拷s name may be entered in only one list.

One of the interesting selection rules is to persuade participants to enter universities in the vicinity of their home towns. This is to help reduce the number of requests for staying in the university dormitories.
The selection process is so complex and so sensitive to many, that EEO has decided to hire the very best programmers in Iran to design a new selection algorithm and write a completely new program for what they have been doing for years. ACM programming contest is where these programmers can be found.

There are N students S1 to SN , and M items F1 to FM , each representing one of the FDUs. There are also a number of geographic regions. For each participant, the total score, the geographic region where his/her high school diploma was awarded, and a priority list of his/her wanted FDUs are available. For each FDU, the geographic region where the corresponding university is located, and its capacity for that year is recorded.

Write a program to compute the list of accepted students with the FDU they can enter to, given the above list of input data. Your program must abide with the following rules:

1. (Local student selection rule) Suppose two students A and B have both selected F in their priority lists and F is in region R. Also suppose that score of A is greater than B's score. Then, if B is from region R (local) and A is from other regions (non-local), and B's score is greater than 70% of A's score, then B has priority over A to enter F. In all other cases A has priority over B to enter F.

2. (Fairness rule) Students should be treated according to their priority list of FDUs. That is, an accepted student will be accepted to the first possible FDU he/she can enter.

Note: We assume that scores are all different integer values.


Input

The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains N (1 <= N <= 150) and M (1 <= M <= 50) followed by N lines, each for one student. The format of these lines is Ri, Mi, K, Fi1, 锟斤拷, FiK in this order. In this line, that is for student i, Ri is his/her region number, Mi is his/her score in the entrance exam, K is the number of FDUs in his/her priority list (0 <= K <= M), and his/her priority list containing the FDU numbers in order of interest. Then there are M lines, one for each FDU. Each line contains Ri, and Ci in that order, which respectively is region number of Fi (the ith FDU) and the capacity of Fi. Note that region numbers are arbitrary integers.

Output

Outputs for different test cases are separated by exactly one blank line. For each test case, you should write N lines, one for each of the N students. If student i has been accepted to FDU Fj, then ith line should contain j, and not accepted, if that student has not been accepted in any FDU of his/her interest.


Sample Input

1
9 2
1 100 2 1 2
2 80 2 2 1
1 90 1 1
2 40 1 2
2 50 1 1
1 60 1 2
2 75 1 1
1 95 1 1
2 30 1 2
1 3
2 4

Sample Output

1
2
1
2
not accepted
2
not accepted
1
2

问题简述

题意:对于给定的n个学生和m所学校,已知学生i的k个期望学校和排名,每个学生的地理位置和分数,以及每所学校的容纳上限,试在满足条件下使其形成稳定匹配。

条件

1.假设学生a,b都有期望学校x,对于x而言,如果a来自x的区域,b不来自x的区域,且a的分数大于70%的b的分数,那么x更倾向于选择a;在其他情况下,x总是选择分数高的学生。

2.一个被录取的学生应该进入到他第一个可能进入的学校。(按优先列表来选择

难点:类似于稳定婚姻算法,但是学生(男生)可能匹配不到学校学校(女生)可能匹配多个学生

所以循环终止条件应改为:任何一个学生或者有匹配,或者已经对所有倾向列表上的学校表白过

条目检索:稳定婚姻算法

输入输出

输入:无难度,t组数据,n个学生,m所学校,n行学生信息(所在区域,分数,期望学校数k,k所期望学校编号),m行学校信息(所在区域,容纳上限)

输出:无难度

使用模板(稳定婚姻算法)

struct Gale_Shapley{
	static const int N=60;
	int n;
	int fg;
	int woman[N][N];        //第i个girl对编号j的boy的好感排位 
	int man[N][N];          //第i个boy第j喜欢的girl 
	int man_match[N],woman_match[N];    //已匹配的男女 
	int p[N];               //第i个boy已经表白的人数 
	void solve(){
		for(int i=0;i<N;i++)p[i]=1;//初始化每个男生表白1次
		memset(man_match,0,sizeof(man_match));
		memset(woman_match,0,sizeof(woman_match));
		fg=true;
        //fg标记当前是否还有人没有匹配
		while(fg){
			fg=false;
			for(int i=1;i<=n;i++){//男生i进行表白
				if(!man_match[i]){//如果没有匹配
					int t=man[i][p[i]++];//男生向下一个倾慕对象表白
					if(!woman_match[t]){//如果女生没有匹配,直接配对
						man_match[i]=t;
						woman_match[t]=i;
					}else if(woman[t][woman_match[t]]>woman[t][i]){
                        //如果女生觉得这个男生比自己现在的更好
						man_match[woman_match[t]]=0;    //抛弃之前的
						man_match[i]=t;
						woman_match[t]=i;
					}
					fg=true;
				}
			}
		}
	}
}T;

AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 200
using namespace std;
typedef struct student{
	int id;            //学生编号 
	int area;          //所在区域 
	int score;         //分数 
	int k;             //中意学校数 
}student;
typedef struct school{
	int area;          //区域 
	int v;             //容量 
}school;
typedef struct matchs{
	int cnt;           //容纳学生数
	int match[N];      //列表
}matchs;
student stu[N];        //学生信息
school sch[N];         //学校信息
matchs fmat[N];        //学校匹配的学生数,和学生列表
int mmat[N];           //学生匹配的学校
int man_match[N][N];   //学生i第j期望的学校
int woman_match[N][N]; //学校i对于学生j的倾向度
int vis[N];            //i是否已经全部表白过 
int p[N];              //当前i要向p[i]表白 
int n,m;               //n学生,m学校 
int rr;                //当前区域 

bool cmp_a(student a,student b){      //比较函数a
	if(a.area==rr&&b.area!=rr){
		if(fabs(a.score-0.7*b.score)<1e-6)return 0;
		else return a.score>0.7*b.score;
	}else if(a.area!=rr&&b.area==rr){
		if(fabs(b.score-0.7*a.score)<1e-6)return 1;
		else return b.score<0.7*a.score;
	}else{
		return a.score>b.score;
	}
}
bool cmp_b(student a,student b){      //比较函数b
	return a.id<b.id;
}

void read(){
	scanf("%d%d",&n,&m);
	int ri,mi,ki,ch;
	memset(man_match,0,sizeof(man_match));
	memset(woman_match,0,sizeof(woman_match));
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&ri,&mi,&ki);
		stu[i].id=i;
		stu[i].area=ri;
		stu[i].k=ki;
		stu[i].score=mi;
		for(int j=1;j<=ki;j++){
			scanf("%d",&ch);
			man_match[i][j]=ch;       //男生i第j喜欢的女生是ch 
		}
	}
	for(int i=1;i<=m;i++){
		scanf("%d%d",&sch[i].area,&sch[i].v);
	}
}
void getRank(){
	for(int i=1;i<=m;i++){
		rr=sch[i].area;
		sort(stu+1,stu+n+1,cmp_a);        //把学生按照学校i的区域排序
		for(int j=1;j<=n;j++){
			woman_match[i][stu[j].id]=j;  //学校i对于学生stu[j].id的倾向度为j
		}
	}
	sort(stu+1,stu+n+1,cmp_b);            //按照学生编号排序,即回归原状
}
void GS(){
	bool fg=1;
	memset(mmat,0,sizeof(mmat));
	for(int i=1;i<=n;i++){
		p[i]=1;
		vis[i]=0;
	}
	for(int i=1;i<=m;i++){
		fmat[i].cnt=0;
	}
	while(fg){
		fg=0;
		for(int i=1;i<=n;i++){            //每个学生进行表白 
			while(!mmat[i]&&!vis[i]){     //直到i匹配到学校,或者再也不能匹配到学校停止
				fg=1;
				if(p[i]>stu[i].k){        //如果i现在已经对所有倾向的学校表白过,则标记
					vis[i]=1;
					break;
				}
				int u=man_match[i][p[i]++];     //i当前想要表白的学校
				if(fmat[u].cnt<sch[u].v){       //如果u学校还有空余,表白成功 
					fmat[u].match[++fmat[u].cnt]=i;
					mmat[i]=u;
				}else if(fmat[u].cnt==sch[u].v){//如果u学校当前没有空余
					int worstrank=0;
					int worstid;
					for(int j=1;j<=fmat[u].cnt;j++){//找到u学校当前列表中最不喜欢的学生
						if(worstrank<woman_match[u][fmat[u].match[j]]){
							worstrank=woman_match[u][fmat[u].match[j]];
							worstid=j;
						}
					}
					if(worstrank>woman_match[u][i]){//如果i比最差的更好,则取代位置
                        //下面两行不能互换!!
                        //易错点
						mmat[fmat[u].match[worstid]]=0;
						fmat[u].match[worstid]=i;
						mmat[i]=u;
					}
				}
			}
		}
	}
	
}
int main(){
	int cases;
	scanf("%d",&cases);
	while(cases--){
		read();
		getRank();
		GS();
		for(int i=1;i<=n;i++){
			if(vis[i])printf("not accepted\n");
			else printf("%d\n",mmat[i]);
		}
		if(cases)printf("\n");
	}
	return 0;
}

参考链接

https://blog.youkuaiyun.com/secfly/article/details/50768559

https://blog.youkuaiyun.com/RaAlGhul/article/details/50686211

<think>好的,我现在需要帮助用户解决在使用Seurat或SingleCellExperiment包时调用subset函数出现的“No cells found”错误。首先,我要理解这个错误通常是什么原因引起的。根据经验,这通常是因为过滤条件设置得太严格,导致没有细胞满足所有条件。用户可能在使用subset函数时,指定了某些metadata的列或基因表达条件,但实际数据中没有符合这些条件的细胞。 接下来,我需要考虑用户提到的两个包:Seurat和SingleCellExperiment。虽然两者的处理方类似,但具体的函数和参数可能有所不同。比如,Seurat的subset函数使用active ident或者某些列的logical条件,而SingleCellExperiment可能通过colData进行筛选。 然后,我需要回顾用户提供的引用内容,看看是否有相关信息。引用[2]提到了单细胞测序流程中的细胞活力评估和过滤步骤,可能在数据预处理时如果细胞活率低,会进行离心或免疫分选,这可能导致后续分析时细胞数量较少。此外,引用[4]提到pK参数需要根据数据集调整,但不确定是否与此错误直接相关。 接下来,可能的解决步骤包括: 1. 检查过滤条件是否正确,是否有拼写错误或者逻辑运算符错误。比如,用户可能使用了“>=”而不是“>”,或者列名错误。 2. 检查metadata中是否存在指定的列。例如,用户可能误写了列名,比如“nFeature_RNA”拼写错误。 3. 确认条件是否过于严格。比如,用户要求nFeature_RNA > 5000,但实际数据中最高只有4000。 4. 使用traceback或last_trace查看错误发生的位置,帮助定位问题。 5. 检查数据是否已经正确加载,是否存在未被正确过滤的情况,比如在之前步骤中已经过滤过细胞,导致现在subset时没有剩余。 另外,用户提到的rlang的last_trace可能是指调试工具,需要指导用户如何利用这些工具追踪错误来源。比如,在R中启用调试模,或者查看错误信息中的具体行号。 可能还需要建议用户逐步测试过滤条件,比如先不加条件,逐步添加,直到找到导致问题的条件。或者使用table函数统计满足条件的细胞数量,提前验证。 最后,结合引用中的内容,可能提到在数据预处理阶段正确评估细胞活力和过滤死细胞的重要性(引用[2]),以及参数调整的必要性(引用[4]),但需要确保这些步骤已经正确执行,避免后续分析时数据不足。</think>在处理单细胞RNA测序数据时,调用`subset`函数出现`No cells found`错误通常由**过滤条件与数据不匹配**导致。以下是分步解决方案: --- ### 1. **检查过滤条件语法** - **问题**:逻辑运算符或列名错误 - **示例代码验证**: ```r # 查看metadata列名 colnames(seurat_obj@meta.data) # Seurat colnames(colData(sce)) # SingleCellExperiment # 检查条件合理性(假设筛选线粒体基因占比) sum(seurat_obj$percent.mt < 5) # 返回符合条件的细胞数量 ``` --- ### 2. **逐步放宽过滤条件** - **问题**:阈值设置过严导致无细胞留存 - **调整方法**: ```r # 示例:逐步降低基因数阈值 subset(seurat_obj, subset = nFeature_RNA > 200) # 从200开始测试 ``` --- ### 3. **验证数据预处理完整性** - **关键点**:确保细胞过滤步骤未清空数据[^2] - 原始数据中细胞活率需>90%,否则需离心或免疫分选 - 使用`table(seurat_obj$orig.ident)`检查样本分布 --- ### 4. **调试工具定位错误** - **使用`rlang::last_trace()`**: ```r options(error = rlang::entrace) # 启用错误追踪 subset(seurat_obj, subset = ...) # 触发错误后运行 rlang::last_trace() # 查看调用栈 ``` --- ### 5. **包特定处理** - **Seurat**: ```r # 确认active identity Idents(seurat_obj) <- "cell_type" # 设置分组依据 subset(seurat_obj, idents = "T_cell") ``` - **SingleCellExperiment**: ```r # 使用colData精确筛选 sce[, colData(sce)$cluster %in% c(1,3)] ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值