本文是2017年9月第2题的题解解析,题目如下。题解代码来自此处。


题解代码如下:
#include<bits/stdc++.h>
using namespace std;
struct Key{//定义Key类
int num;//钥匙编号
int time;//当前时间
bool borrow;//表示是取钥匙还是还钥匙 ,true表示取,false表示还
Key(int n,int t,bool b):num(n),time(t),borrow(b){}//构造函数
bool operator<(const Key&k)const{//重载<运算符 ,注意优先级队列默认以最大元素为队首元素
if(this->time!=k.time)//以时间最早的位于队首
return this->time>k.time;
else if(this->borrow!=k.borrow)//先还钥匙再取钥匙
return this->borrow&&!k.borrow;
else//以钥匙编号最小的位于队首
return this->num>k.num;
}
};
priority_queue<Key>pq;//优先级队列
int main(){
int N,K;
scanf("%d%d",&N,&K);
int a[N+1];//表示当前挂钩上钥匙顺序的数组
for(int i=0;i<N+1;++i)
a[i]=i;
for(int i=0;i<K;++i){//读取数据
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
pq.push(Key(a,b,true));
pq.push(Key(a,b+c,false));
}
while(!pq.empty()){//队列不空,继续循环
Key k=pq.top();
pq.pop();
if(k.borrow){//如果是取钥匙
int i=1;
while(a[i]!=k.num)//查找取的钥匙编号在数组中的位置
++i;
a[i]=-1;//令该位置处钥匙编号为-1,表示该挂钩没有挂钥匙
}else{//如果是还钥匙
int i=1;
while(a[i]!=-1)//查找数组中第一个没挂钥匙的挂钩
++i;
a[i]=k.num;//令该位置处钥匙编号为还的钥匙编号
}
}
for(int i=1;i<N+1;++i)//输出
printf("%d ",a[i]);
}
1 将一条人员数据分成两条数据,这两条数据分别与同一个人借钥匙,还钥匙相关。
2 优先队列 及重载小于号(模拟某一时刻多个人借、还钥匙的优先级)。
3 队列本身的方法和操作。
4 C++ struct 关于构造函数的特性。
- 将一条人员数据分成两条数据,这两条数据分别与同一个人借钥匙,还钥匙相关。
题目中是说w s c,我只能想到把这三个数据项同时存储在一个结构体中,或者分别存储在3个数组中。但是实际上可以通过是“借”还是“还”来分开存储。因为借的时间和还的时间都是时间把。 - 优先队列 及重载小于号(模拟某一时刻多个人借、还钥匙的优先级)。
bool operator<(const Key&k)const{//重载<运算符 ,注意优先级队列默认以最大元素为队首元素
if(this->time!=k.time)//以时间最早的位于队首
return this->time>k.time;
else if(this->borrow!=k.borrow)//先还钥匙再取钥匙
return this->borrow&&!k.borrow;
else//以钥匙编号最小的位于队首
return this->num>k.num;
}
重载的是小于号,函数返回值类型是 bool,形式参数那是const Key& k,其中 const Key是const + 类型 ,& k是&+变量名。函数体前也有一个const。
首先关于“<”,由于注意优先级队列默认以最大元素为队首元素。这句话不太好理解,但是可以这样理解,就是重载之后的小于号,a<b是什么意思,是a “<” b,这种小于不再是以前小学就开始学的算术意义的小于,是重载之后的小于,小于号的右边是b左边是a也就是在优先队列中b会出现在a之前。
下面第一种情况是if(this->time!=k.time) 如果this->time和k的time不一样,如果this->time>k.time 如果this指向的time比k的time大,则this指向的key小于k,结合上面解释过的重载小于号的内涵,不难理解,这个if语句想表达的就是time越小越优先,越出现在优先队列的前面。
看下面的语句else if(this->borrow!=k.borrow) return this->borrow&&!k.borrow;就是说,如果两个元素时间相等怎么比较?如果它们不是同时借,或者同时还,那么只有当左边的元素是借,右边是还,才是左边小于右边,即右边出现在有限队列的更前边。另外一种情况无非就是左边元素是“还”,右边是“借”。其实就是模拟了题意:先还再借。
接下来return this->num>k.num;,如果左右两个元素的time一样,还同时借或者同时还,怎么办?那么只有左边元素的num比右边的大,这才是左边小于右边,右边的元素在优先队列中更接近头部。其实就是先处理num小的。
- 队列本身的方法和操作。
while(!pq.empty()){//队列不空,继续循环
如果队列不空。
Key k=pq.top();
pq.pop();
先找到队列中第一个元素,然后把它pop(),注意元素pop()掉就不存在了,所以需要保存下来。
- C++ struct 关于构造函数的特性。
Key(int n,int t,bool b):num(n),time(t),borrow(b){}//构造函数
结构体中只写了一个构造函数。
Key k=pq.top();
是可行的
pq.push(Key(a,b,true));
pq.push(Key(a,b+c,false));
也是可行的。
但是
Key k;
不可行,为肾么呢?
3930

被折叠的 条评论
为什么被折叠?



