PAT 1014 Waiting in Line (30 分) 测试点(1、4、5)

我靠!我tm终于ac了,从凌晨1点半写到5点钟,没错,我他妈和它杠上了。

 

思路:建立N个队列,先将队列内的N*M个人排满(不够就break,多了之后处理)。队列内存consumer的id和当前服务所需的时间,用pair<id,time>即可。

每次寻找队列头的最小值,然后每个队列头的当前所需时间减去最小值(防止多个用户所需时间相等),

当各个队列头为0时,1、更新结果集 2、弹出当前队列头。3、如果有新人,插入

代码:

//顾客只要是在17:00前开始服务的都可以被服务完,所以判断条件里还要加上这一条;及代码中注释部分   真尼玛坑啊    17:00是开始时间,17:59是结束时间
#include<iostream>
#include<vector>
#include<map>
using namespace std;

bool all_empty(vector< pair<int,int> > queues[],int n){
    for(int i=0;i<n;i++){
        if(queues[i].size()!=0) return false;
    }
    return true;
}

string to_time(int t){
    string ans;
    int h=t/60+8+100,m=t%60+100;
    string hh=to_string(h),mm=to_string(m);
    hh.erase(hh.begin());mm.erase(mm.begin());
    ans = hh+":"+mm;
    
    return ans;
}

int main()
{
    int n,m,k,q;
    cin>>n>>m>>k>>q;
    //记总时间
    int t=0;
    //记结果
    map<int,int> ans;    //[id]---[08:07]
    //生成n个队列
    vector< pair<int,int> > queues[n];   //pair<id,time>
    //把人放进去
    int id=1,time,flag=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(id>k){
                flag=1;break;
            }
            cin>>time;
            queues[j].push_back(make_pair(id,time));
            id++;
        }
        if(flag==1) break;
    }
    //开始把人放出来,如果k》m*n,有人进来再处理就好了。
    while( !all_empty(queues,n) ){
        //先计算最小值,再都减去最小值,为0的弹出的同时新进人。
        int min=999;
        for(int i=0;i<n;i++){
            if(queues[i].size()==0) continue;
            if(queues[i].begin()->second < min) min=queues[i].begin()->second;
        }

        if(t+min>=540){   //下次循环点就17:00不服务了,把这次的都服务完!!!!!!!!!!!!!!!!!!!测试点5
            for(int i=0;i<n;i++){
                if(queues[i].size()==0) continue;
                auto it=queues[i].begin();
                ans[it->first]=(t+it->second);
                
            }
            break;
        }
        t=t+min;
            for(int i=0;i<n;i++){
                if(queues[i].size()==0) continue;
                auto it=queues[i].begin();
                it->second -=min;
                if(it->second==0){
                //弹出it          1、更新结果集 2、如果有新人,插入 3、弹出
                ans[it->first]=(t);
                queues[i].erase(it);        //这里很重要,如果放在后面会报段错误,考虑是不是由于增加了元素导致id变了。!!!!!!!!!!!!!!!!!!!!!!!!!!!!!测试点1
                if(id<=k){                  //这里虽然队列入队出队结束了,但是还有数没有读完!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!测试点4
                    cin>>time;
                    queues[i].push_back(make_pair(id,time));
                    id++;
                    }   
                }
            }
        
    }
    for(;id<=k;id++){
        int temp;
        cin>>temp;
    }
    
    for(int i=0;i<q;i++){
        int q_id;
        cin>>q_id;
        if(ans.count(q_id) ) cout<<to_time(ans[q_id])<<endl;
        else cout<<"Sorry"<<endl;
    }
    
    
    
}

巨坑的点!!!!!!!!!!!!!!!!!!

测试点1:段错误

这里我没搞懂,弹出和插入新人的步骤交换后会出现这个结果,考虑是不是push_back把迭代器it给变了。

测试点5:答案错误

这里是大家都反馈的点,是开始时间在17:00之前的,就可以服务到不能呼吸哦!

这里发现之后也是想了好久,在t+min>540后,把当前的服务全部结束掉。

(最开始直接t>540发现有的进行一半的服务被我停止了,因为没记录开始时间,让我一度怀疑自己要重新设计,构建个结构包含开始时间,结束时间啥啥的,当时已经4点了,能懂我崩溃的心情吗)

案例:

2 1 3 3
3 540 540
1 2 3

结果:

08:03
17:00
17:03

测试点4:答案错误

因为我的代码时一边读取一边处理,导致服务时间大于540的时候队列结束了,第2行数据没读取完,就串行了,找了好久。!!!!

案例:

2 1 5 3
3 540 540 1 2
1 2 3

 结果:

08:03
17:00
17:03

我之前的错误结果(这样猜一眼发现错哪了):

08:03
17:00
08:03
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值