【问题描述】
在 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位的字符串,表示需要查询的身份证号
【输出形式】
输出为 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
【代码框架】
建议复制以下代码框架, 在此基础上完成本题需求。此建议不是必须,你可以忽略。
#include <iostream>
using namespace std;
struct people
{
char id[19]; /* 身份证号码 */
int social; /* 社保缴纳月数 */
int area; /* 现有住房面积 */
char date[11]; /* 申报日期 */
};
people* getMess(int &n);
int main()
{
people *person; /* 指向所有报名人的基本资料首地址,通过调用函数getMess获取 */
int n; /* n为报名人数,通过调用函数getMess获取 */
person=getMess(n);
// ...
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%的用例无同等条件的数据,30%的用例只有刚性需求,20%的用例只有改善性需求。
测试用例十数据规模较大,需要算法优化。
【文件下载】
请下载压缩文件 并在存放源程序文件的文件夹下解开,其中二进制文件house.bin包含了相关的测试数据,test.txt是相关测试数据的文本格式,可用于程序测试
【思路】
按照题目要求进行排序~ 然后计算每个人的排位(序号)~根据需要输出即可~具体看代码吧~
一)文件的读取和储存
创建结构体数据储存,按照题目所给模板,储存所有报名人的资料
二)处理报名人信息
1.确定是否能买房
如果其不满足买房需求,即绝对不能买房,打上标记
2.处理提交日期信息
1)字符串向数字转化:直接根据格式,按照位置转化即可
2)日期转化:把所有的日期转化为天数
三)排序
优先级参数:
1.绝对无法买房的标记参数(无法买房排在后面)
2.面积 > 提交日期
3.面积相等,居住月份 > 提交日期
四)处理排位问题
1.相等排位:按照排序结果给予买房者序号,若某个人信息和前一个人一模一样,则序号和前一个人相等
2.其余按照顺序给予序号
五)剩余选房数
得到每个人的剩余选房数(即为到达【自己水平】的时候的剩余数)
六)输出
1.能够买房:输出序号
2.多人能够买房:向上和向下寻找序号一致的人,作为序号开始和结束的区间
3.多人抢房:向上向下记录同一序列的人数,输出剩余房数/人数
4.绝对无法买房或者房数不够:正常输出
【AC代码】
#include <iostream>
#include <algorithm>
#include <vector>
#include<string>
using namespace std;
struct people
{
char id[19]; /* 身份证号码 */
int social; /* 社保缴纳月数 */
int area; /* 现有住房面积 */
char date[11]; /* 申报日期 */
};
people* getMess(int &n);
struct human
{
string name; //姓名
int months; //居住时长 月份
int S; //居住面积
int time; //提交申请的时间
int rank; //在买房的人中排名多少
int has_house; //是否能够买房
int remain; //到达该人时还有多少房
human(){
has_house=1; //默认能够买房
}
};
bool cmp(human a,human b){
if(a.has_house != b.has_house )
{return a.has_house >b.has_house ;} //不能买房的在后面
if(a.S ==0 && b.S == 0 ) //面积相等
{
if(a.months != b.months)
{
return a.months >b.months ; } //先比较居住月份
else
{
return a.time <b.time ;} //最后比较提交购买的时间
}
if(a.S != b.S)
{ return a.S < b.S ;} //比较居住面积,小的优先
else {
return a.time <b.time ; //先提交申请的优先
}
}
int main()
{
people *person; /* 指向所有报名人的基本资料首地址,通过调用函数getMess获取 */
int n; /* n为报名人数,通过调用函数getMess获取 */
person=getMess(n);
int no_house=0; //绝对无法买房的人数
human* h=new human[n];
for(int i=0;i<n;i++){
h[i].name = person[i].id ; //身份证
//cout<<h[i].name;
h[i].months=person[i].social ; //月数
h[i].S =person[i].area ;
if(h[i].S==0 && h[i].months<=24) { //无法买房的人
h[i].has_house =0;
no_house++;
}
string temp=person[i].date;
h[i].time =(temp[0]-'0')*10*30+(temp[1]-'0')*30 +
(temp[3]-'0')*10+(temp[4]-'0')+
(temp[6]-'0')*1000*365+(temp[7]-'0')*100*365+(temp[8]-'0')*10*365+(temp[9]-'0')*365;
}
sort(&h[0],&h[n],cmp); //.....sort导致运行时错误!!!!!
// for(int i=0;i<n;i++) cout<<h[i].name <<" "<<h[i].months << " "<<h[i].S << " " <<h[i].time <<" "<<h[i].rank <<endl;
- 输入环节 -
int m;
int T;
cin>>m>>T;
int num=n-no_house;
for(int i=0;i<num;i++) //处理排位问题以及能否买房问题
{
h[i].rank=i+1;
if(i>0) { // 全都要比较!!!!
if(h[i].S==0 && h[i-1].S==0 ){
if(h[i].months == h[i-1].months && h[i].time == h[i-1].time )
{
h[i].rank =h[i-1].rank ;
}
}
else if(h[i].S == h[i-1].S && h[i].S!=0 && h[i-1].S!=0) {
if(h[i].time == h[i-1].time){
h[i].rank =h[i-1].rank ;
}
}
}
}
for(int i=0;i<num;i++){ h[i].remain = m-i; } //每个人的剩余可选房数
while(T--){
string a_name;
cin>>a_name;
int pos=0;
for(int i=0;i<n;i++)
{
if(h[i].name == a_name) //以后 if,else后面统统加 { } !!!!!
{
pos=i;
break;
}
}
//- 判断输出 -/
if(h[pos].has_house ==0){ //绝对没法买房的刚性需求户
cout<<"Sorry"<<'\n';
}
else {
int num_house=0;
int num_same_rank=-1;
for(int i=pos;i<num;i++){ //往下找相同位次的
if(h[i].rank != h[pos].rank ) break;
else {
num_same_rank++;
}
}
for(int i=pos;i>=0;i--){ //往上找相同位次的
if(h[i].rank == h[pos].rank ){
num_house=h[i].remain ;
num_same_rank++;
}else break;
}
if(num_same_rank==1){ //该位次只有一个人
if(num_house<=0) cout<<"Sorry"<<'\n';
else cout<<h[pos].rank<<'\n';
}else{
if(num_house<=0) cout<<"Sorry"<<'\n';
else if(num_house>=num_same_rank){ //如果房子足够
cout<<h[pos].rank <<" "<<h[pos].rank +num_same_rank-1<<'\n';
}else {
cout<<num_house<<"/"<<num_same_rank<<'\n';
}
}
}
}
return 0;
}
//- 读入信息,得到人数n -/
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;
}
【写在后面】
对你有帮助记得点个赞哦~有啥问题请留言~