湖南大学实训1-8:买房与选房

文章描述了一个基于社保缴纳月数和住房面积的住房分配政策,优先满足刚性需求,再处理改善性需求。开发商使用排序算法处理申请人信息,依据身份证号、社保月数、住房面积和申报时间决定选房顺序。程序处理二进制文件中的申请数据,并提供查询功能,输出申请者的选房资格和顺序。
摘要由CSDN通过智能技术生成

【问题描述】

在 X 国许多一线城市住房非常紧张,政府部门制定了相关的政策,重点满足住房刚性需求(住房面积为0,社保缴纳必须超过2年),然后才能照顾改善性需求(住房面积大于0)。

具体的原则为:
对于刚性需求,缴纳社保月数多者优先。
对于改善性需求,现有自有住房面积小者优先。

由于房源有限,为公平起见,开发商在不违背上述原则下特意指定同等条件下申报时间同时作为排队的条件,时间越早优先级越高。

最近有一批新楼盘准备开盘,总共有 m (≤1000)套房,所有的网上申报工作都已经完成并保存到二进制文件house.bin中,申请者提交了自己的基本材料,格式为:身份证号(18位,加1位空字符’\0’,共19位)、社保缴纳月数、自有住房面积、申报时间(格式为:MM-DD-YYYY,10位字符串,加1位空字符’\0’,共11位),社保缴纳月数、自有住房面积均为整数,文件最后为总报名人数 n(≤105)。
申请者可以通过身份证号查询最终的结果。

【输入形式】

输入的第一行为两个正整数 m(≤1000)和 T ( T ≤ n ),分别表示本次开盘的楼盘可供申请的套数以及查询的组数。

接下来的 T 行,每行为一个18位的字符串,表示需要查询的身份证号。
1
2
3

【输出形式】

输出为 T 行,对应每个查询的输出结果:

   1. 申请者不符合购房条件或排位超出了所推出的房源数量不能中签,则输出"Sorry";

   2. 申请者符合购房条件,且该名次人数为1人,则直接输出一个整数,表示选房顺序号;

   3. 申请者符合购房条件,且该名次人数有多人,同时人数不大于所剩房源数量,则直接输出用空格分隔的两个整数,表示选房顺序号区间;

   4. 申请者符合购房条件,且该名次人数有多人,同时人数大于所剩房源数量,则输出用/分隔两个整数,如 A/B,表示 B 人中选 A 人,选房顺序为排名倒数 A 名范围。

【样例输入】

9 6
350102200609166049
350102200609163286
250342323545313434
130502201805070787
110101196003074525
430102201102181455

【样例输出】

2
3 4
Sorry
6
2/3
Sorry

【测试样例说明】

10%的用例无同等条件的数据,30%的用例只有刚性需求,20%的用例只有改善性需求。

【思路解析】

  • 重要的是题目的理解。我们只给三种人分配房子:
  1. area不等于0,social不做要求
  2. area等于0,但是social必须大于等于24
  • 所以不满足分房要求的便是area等于0且social小于24的。
  • 为了便于struct使用sort函数,我们可以设置一个内部的重载<函数,这个重载函数中进行前一个与后一个people的比较。特别注意该函数在优先级完全相同的情况下返回的是false,原因是:79行有一处person的比较,实际上的语句应该是 if(person[i]!=person[i+1]) ,但是为了偷懒就使用了<,所以在俩个people优先级完全相同的情况下要返回false。
  • 99行所剩房源数res,一开始我是没有想通的,以为存入的rank是 1 1 1 2 2 2 3 3 这样的,但其实是 1 1 1 4 4 4 7 7 。
  • 最后提一下重载函数中的优先级比较:
  1. 满足分房要求的放在前面,不满足的放在后面
  2. 对于满足分房要求的人,area都等于0时比较social
  3. area不相等时(有一个area=0或者俩area都不等于0)返回area较小的
  4. area相等时比较social,social相等比较date

【AC代码】

#include <iostream>
#include<map>
#include<algorithm>
using namespace std;

struct people

{

    char id[19];                  /* 身份证号码 */

    int social;                     /* 社保缴纳月数 */

    int area;                       /* 现有住房面积 */

    char date[11];              /* 申报日期 */
	
	/* 满足条件的、优先级大的放在前面 */
	bool operator<(const people &b) const
	{
		/* 本身不满足条件直接往后放就是 */ 
		if(area==0&&social<=24) return false;
		/* 如果本身满足条件而下一个preson不满足 */ 
		if(b.area==0&&b.social<=24) return true;
		/* 说明本身或者下一个person有area!=0 */
		if(area!=b.area) return area<b.area;
		else{
			if(area==0&&social!=b.social) /* area=b.area=0 */
				return social>b.social;
			else{
				/* 比较日期 */
				for(int i=6;i<=9;i++){
					if(date[i]!=b.date[i]) 
						return date[i]<b.date[i];
				}
				for(int i=0;i<=1;i++){
					if(date[i]!=b.date[i]) 
						return date[i]<b.date[i];
				}
				for(int i=3;i<=4;i++){
					if(date[i]!=b.date[i]) 
						return date[i]<b.date[i];
				}
			}
		}
		/* 两者优先级完全相同 */
		return false;
	}
};

people* getMess(int &n);

int main()

{

    people *person;          /* 指向所有报名人的基本资料首地址,通过调用函数getMess获取 */     

    int n;                            /* n为报名人数,通过调用函数getMess获取 */

    person=getMess(n);
	
	int m,T;
	
	cin>>m>>T;
	
	sort(person,person+n);
	
	map<string,int> rank;/* <id,rank> */ 
	map<int,int> rank_cnt;/* <rank,相同rank的cnt> */
	
	/* 把person中的数据存在map中 */
	rank[person[0].id]=1;
	rank_cnt[1]=1;
	for(int i=0;i<n-1;i++){
		if(person[i].area==0&&person[i].social<=24){
			rank[person[i].id]=-1;
		}
		if(person[i]<person[i+1]){
			rank[person[i+1].id]=i+2;
			rank_cnt[rank[person[i+1].id]]=1;
		}
		else{
			/* 由于之前进行过sort */
			/* 所以person[i]==person[i+1] */
			rank[person[i+1].id]=rank[person[i].id];
			rank_cnt[rank[person[i].id]]++;
		}
	}
	
	string id;
	while(T--){
		cin>>id;
		if(rank[id]>m||rank[id]<0) cout<<"Sorry"<<endl;
		else{
			int num=rank_cnt[rank[id]];
			if(num==1) cout<<rank[id]<<endl;
			else{
				int res=rank[id]-1;//所剩房源数吧 
				if(res+num<=m) cout<<rank[id]<<" "<<res+num<<endl;
				else cout<<m-res<<"/"<<num<<endl;
			}
		}
	}

    return 0;

}

people* getMess(int &n)            /* 将文件数据读入内存 */

{

    FILE *fp;

    fp=fopen("house.bin","rb");

    fseek(fp,-1*(long)sizeof(int), 2);

    fread(&n, sizeof(int),1, fp);

    rewind(fp);

    people *tmp=new people[n];

    fread(tmp, sizeof(people), n, fp);

    fclose(fp);

    return tmp;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awars_zpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值