这一题简直要吐血= =从昨天下午开始搞,写了三版,想了数组、队列、结构体,但总是有步骤不对,好像哪里没有整合到一块,零零散散的感觉。。
今天睡一觉起来就觉得有思路了,吃过饭写了一会,可算搞出来了~(PS:这要是考试可怎么办= =)
说下思路:
1、用结构体存每个ID的信息,主体是time,想要让它们顺着一维的时间去执行,打个比方,编号1在10拿钥匙,拿了7小时,也就是17放回钥匙,那么就记录两条信息,一个time为10,一个time为17;同时再用signal记录下这个时刻是拿钥匙还是放钥匙(代码里signal = 1,表示拿钥匙,signal = 0表示还钥匙)
2、结构体需要再存放一个op,也就是此时此刻拿钥匙的时候,这个ID所在的位置,这句话是理解这一题的关键!!钥匙来来去去,但位置就那么几个,变化的是空出来的位置!!
3、用优先队列来模拟整个拿钥匙、放钥匙的过程,因为题目说每次放钥匙的时候,总是从左边(从小的剩余位置开始考虑),优先队列让小数优先级在前,自然满足~
4、给这些结构体排序,按照时间从小到大、时间相同,按先放钥匙再拿钥匙,都相同,按编号从小开始处理
5、单弄一个数组ans[],用来存每次变动完,有钥匙的位置存放的钥匙ID(开始想用map,但map不熟,就还用结构体了)
AC代码:
#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;
struct node{
int id,time,op;
int signal; //signal = 1,表示拿钥匙,signal = 0表示还钥匙
}G[2010];
bool cmp(node a,node b){
if(a.time != b.time){
return a.time < b.time; //按时间从小到大排序
}
else if(a.signal != b.signal && a.time == b.time){
return a.signal < b.signal; //按先还再取
}
else if(a.signal == b.signal && a.time == b.time && a.id != b.id){
return a.id < b.id; //都一样按编号从小到大
}
}
int main(){
int N,K;
int sympol = 0; //计数用
int x,y,z;
int ans[1000];
scanf("%d %d",&N,&K);
for(int i = 1;i<=N;i++){ //初始认为每个位置放各自编号
ans[i] = i;
}
for(int i = 0;i <K;i++){
scanf("%d %d %d",&x,&y,&z);
G[sympol].id = x;
G[sympol].time = y;
G[sympol].signal = 1;
G[sympol].op = x; //初始默认拿钥匙时在自己位置
sympol++;
G[sympol].id = x;
G[sympol].time = y+z;
G[sympol].signal = 0;
sympol++;
}
sort(G,G+sympol,cmp);
priority_queue <int,vector<int>,greater<int> > q;
for(int i = 0;i <sympol;i++){
if(G[i].signal == 1){ //拿钥匙
q.push(G[i].op); //把位置入队列
}
else{
int t = q.top(); //还钥匙
ans[t] = G[i].id; //t位置放新的id
G[i].op = t; //更新它的位置
for(int j = i;j < sympol;j++){ //往后如果有再拿钥匙,变更存放位置
if(G[i].id == G[j].id && G[j].signal == 1){
G[j].op = G[i].op;
break;
}
}
q.pop(); //还好钥匙,出队
}
}
for(int i = 1;i <=N;i++){
printf("%d ",ans[i]);
}
}