PAT 甲级 1014 Waiting in Line (30 分)(queue的使用,模拟题,有个大坑)

1014 Waiting in Line (30 分)
 

Suppose a bank has N windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. The rules for the customers to wait in line are:

  • The space inside the yellow line in front of each window is enough to contain a line with M customers. Hence when all the N lines are full, all the customers after (and including) the (st one will have to wait in a line behind the yellow line.
  • Each customer will choose the shortest line to wait in when crossing the yellow line. If there are two or more lines with the same length, the customer will always choose the window with the smallest number.
  • Customeri​​ will take Ti​​ minutes to have his/her transaction processed.
  • The first N customers are assumed to be served at 8:00am.

Now given the processing time of each customer, you are supposed to tell the exact time at which a customer has his/her business done.

For example, suppose that a bank has 2 windows and each window may have 2 custmers waiting inside the yellow line. There are 5 customers waiting with transactions taking 1, 2, 6, 4 and 3 minutes, respectively. At 08:00 in the morning, customer1​​ is served at window1​​ while customer2​​ is served at window2​​. Customer3​​ will wait in front of window1​​ and customer4​​ will wait in front of window2​​. Customer5​​ will wait behind the yellow line.

At 08:01, customer1​​ is done and customer5​​ enters the line in front of window1​​ since that line seems shorter now. Customer2​​ will leave at 08:02, customer4​​at 08:06, customer3​​ at 08:07, and finally customer5​​ at 08:10.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers: N (≤, number of windows), M (≤, the maximum capacity of each line inside the yellow line), K (≤, number of customers), and Q (≤, number of customer queries).

The next line contains K positive integers, which are the processing time of the K customers.

The last line contains Q positive integers, which represent the customers who are asking about the time they can have their transactions done. The customers are numbered from 1 to K.

Output Specification:

For each of the Q customers, print in one line the time at which his/her transaction is finished, in the format HH:MM where HH is in [08, 17] and MM is in [00, 59]. Note that since the bank is closed everyday after 17:00, for those customers who cannot be served before 17:00, you must output Sorry instead.

Sample Input:

2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7

Sample Output:

08:07
08:06
08:10
17:00
Sorry

题意分析:

(1)本题模拟银行排队,逻辑上不难,操作起来有点麻烦。银行来了K个客户,银行有N个窗口,每个窗口前有M个位置排队,客户选择最短的队伍排,根据每个客户的序号和服务时间来确定最后客户离开银行的时间。

(2)属于队列的问题,但实际上可以将问题简化:因为每个客户的服务时间是固定的,假设前N*M个客户达到之后排好位置后,他们的离开时间也就确定好了,即每个窗口本次服务结束的时间也就确定了,比如第一个人的服务时间是5min,则本次窗口的服务结束时间点是8:05,这样我们就可以比较这N个窗口当前服务结束的时间点,谁最早结束,谁的队伍最短,在线外等候的第N*M+1个客户选择这个队伍排,以此类推。

(3)每个客户离开的时间等于他前面一个人的离开时间加上他自己的服务时间,于是定义每个队列中的值是前一个值加上这个人的服务时间

(4)为了计算方便,将时间的基点设为0,算出的结果是在银行停留的时间(以分钟计算),最后再换算成小时+8

可能坑点:

(1)这是个大深坑,必须要保证当一个人等待时间大于或等于540分钟的时候,就不能服务了,而不是等待时间加上他的服务时间,言外之意就是,一旦这个人在540分钟之内获得服务,那么无论这个人的服务时间有多长,也要为他服务完,这也是符合实际的。

 

#include<bits/stdc++.h>
using namespace std;
queue<int>q[105];
int a[2005];//服务时间 
int ct[2005];//还需多少时间 
int t[2005];//服务结束的时间 
int N,M,K,Q;
void clear(queue<int> &q)
{
    queue<int> empty;
    swap(empty, q);
}
int main(){
    cin>>N>>M>>K>>Q;
    for(int i=1;i<=N+1;i++){
        clear(q[i]);
    }
    for(int i=1;i<=K;i++)
    {
        cin>>a[i];
        ct[i]=a[i];
        t[i]=99999;
    }
    //先把他们再队伍里放好
    int p=min(N*M,K);
    for(int i=1;i<=p;i++)//这里出现了错误,后来知道要选择最小的 
    {
        int x=i%N;
        if(x==0) x=N;
        q[x].push(i);
    }  
    if(K>=N*M+1)
    {
        for(int i=N*M+1;i<=K;i++){
             q[N+1].push(i);
        }    
    }
     //先标记最前面一排的人的时间
    int T=0; 
    while(1)
    {
         //每次挑出队列最前面的人群中的最少时间 
        int min_t=99999;
        int is_all_empty=1;
        for(int i=1;i<=N;i++)
        {
            if(!q[i].empty())
             {
                 min_t=min(min_t,ct[q[i].front()]);
                 is_all_empty=0;
             }
        }
        if(is_all_empty==1){
            break;
        }
        T+=min_t;//从开始到现在过去了T分钟 
        
         //那么每个人减去这个时间,并把下一个人排进队伍
        for(int i=1;i<=N;i++)
        {
            //cout<<"遍历第"<<i<<"个窗口"<<endl;
            if(!q[i].empty())//要先判断,否则会有段错误,这里错过一次 
            {

                 ct[q[i].front()]-=min_t;
                 if(ct[q[i].front()]==0){
                     //cout<<i<<"窗口完成 "<<q[i].front()<<" 时间为"<<T<<endl;
                     //完成了
                     t[q[i].front()]=T; //设置他们结束的时间 
                    q[i].pop();        
                     //新的人可以入队啦
                    if(!q[N+1].empty()) 
                    {
                        int x = q[N+1].front();
                        q[N+1].pop(); 
                        q[i].push(x);    
                        //cout<<x<<"加入到 "<<i<<" 窗口"<<endl;
                    }
                }
            }
        }
        //大坑!!!特殊处理 
        if(T>=540){
            //仍要坚持把当前再服务的人服务完 
            for(int i=1;i<=N;i++)
            {
                if(!q[i].empty())
                 {
                     int x=q[i].front();
                     if(ct[x]!=a[x])//处理到一半的继续处理 
                     {
                         t[x]=T+ct[x];
                    }
                 }
            }
            break;
        } 
    }
    //输出时间 
    for(int i=1;i<=Q;i++)
    {
         int x;
         cin>>x;
         if(t[x]==99999)
        {
             cout<<"Sorry"<<endl;
        }
        else
        {
             int h=t[x]/60;
             int m=t[x]-h*60;
             h+=8;
             if(h<10)
             {
                 cout<<'0';
            }
            cout<<h<<":";
            if(m<10)
            {
                 cout<<'0';
            }
            cout<<m<<endl;
        }
         
    }    
    return 0;
} 

 

 

转载于:https://www.cnblogs.com/caiyishuai/p/11291689.html

### 关于 PAT 甲级 2023 冬季考试中的层图题目 在 PAT 甲级考试中,涉及层图的题目通常围绕图结构展开,可能涉及到 BFS 或 DFS 的应用来解决特定问题。虽然目前尚未提供具体针对 2023 年冬季考试的相关官方资料,但从以往的经验来看,层图类题目主要考察以下几个方面: #### 图的存储与遍历 为了高效处理大规模数据集(如 N ≤ 10^4),推荐使用邻接表而非邻接矩阵存储图结构[^1]。这种存储方式能够显著减少空间复杂度并提高访问效率。 #### 层次划方法 当需要计算节点层次或深度时,BFS 是一种常用的选择。通过引入特殊的标记点(例如 `0`)作为层间隔符,可以在每次迭代结束后轻松识别当前所处的层数。此外,在某些情况下也可以利用嵌套循环的方式逐层处理节点集合[^2]。 #### 应用场景扩展 除了基础的连通性路径长度析外,层图还经常被应用于更复杂的实际问题求解当中。比如: - **最短路问题**:基于不同权重定义构建多阶段网络模型; - **动态规划转移方程设计**:借助层思想降低状态维度从而简化计算过程; - **资源配优化**:结合贪心策略合理安排有限资源以满足全局目标约束条件[^3]。 以下是采用 Python 实现的一个简单示例程序片段用于演示如何运用上述技术完成类似任务: ```python from collections import deque, defaultdict def bfs(graph, start_node): visited = set() queue = deque([(start_node, 0)]) # Tuple format: (current_node, level) max_level = -float('inf') while queue: node, level = queue.popleft() if node not in visited: visited.add(node) # Update maximum depth encountered so far. max_level = max(max_level, level) for neighbor in graph[node]: if neighbor != 0 and neighbor not in visited: # Skip the layer separator '0'. queue.append((neighbor, level + 1)) return max_level if __name__ == "__main__": edges = [[1, 2], [1, 3], [2, 4], [3, 5]] adj_list = defaultdict(list) for u, v in edges: adj_list[u].append(v) adj_list[v].append(u) deepest_root_depth = bfs(adj_list, 1) print(f"The deepest root has a depth of {deepest_root_depth}.") ``` 以上代码展示了如何通过广度优先搜索算法找到给定无向图中最深叶子节点所在的高度。 #### 总结 综上所述,解答此类层图相关的问题需综合考虑多种因素,并灵活选用适当的数据结构技术手段加以应对。希望这些信息能对你有所帮助! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值