您的位置:首页 > 大数据 > 人工智能

PAT 1014 Waiting in Line(模拟+队列操作)

2017-05-28 10:31 471 查看

题目

https://www.patest.cn/contests/pat-a-practise/1014

银行前台处理客户的过程如下,有n个窗口,每个窗口前的队伍可以排m个人,其余人在黄线外等待;每当有人处理完毕时,黄线外的人找最短的、序号最小队伍插入;求每个人的结束时间。

解题思路

本题是明显的队列的模拟题,遗憾的是改了好久代码只过了四组,最后一组依然是段错误,虽然还不知道什么原因:(,看了一下网上大神的代码,非常简练明了,五体投地。(参考:http://blog.csdn.net/acm_ted/article/details/20473255

先把n*m个客户加入对应的n的窗口队列中,如果还有客户,枚举判断出n个窗口中最早处理完的队列,然后将用户加入此队列。

最后将时间和时限进行比较,输出。

和自己实现的相比,有两个最大的不同:

为每个客户构造一个结构体,记录耗时,开始时间和结束时间

利用了每位顾客插入队伍时,就决定了什么时候轮到他,什么时候离开,因此没必要完全模拟,处理直到所有队列都为空,不然会比较杂乱不够清晰

需要注意的是,如果一个顾客在17:00前(<=16:59)能轮到即可,不要求在17:00前处理完毕。

AC代码

参考别人博客修改后的代码

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxcnt = 1005;
const int maxn = 25;

typedef struct node
{
int wasteTime; //每位顾客耗时
int sTime,eTime; //开始和结束时间
}customer;

typedef struct windows
{
int eTime; //本窗口处理完的时间
queue<int> q;
}window;

///利用了每位顾客插入队伍时,就决定了什么时候轮到他,什么时候离开,没必要完全模拟直到队列都空了
int main()
{
customer cust[maxcnt];
window win[maxn];
int n,m,cnt,q;
int num, minTime, idx, pos;
cin >> n >> m >> cnt >> q;
for (int i = 1; i <= cnt; ++i)
cin >> cust[i].wasteTime;
num = 1;
int first = min(n*m, cnt);
for (int i = 0; num <= first; ++num, i=(i+1)%n) //插入第一批顾客
{
cust[num].sTime = win[i].eTime;
cust[num].eTime = cust[num].sTime + cust[num].wasteTime; //顾客的时间确定,用于输出他自己
win[i].eTime += cust[num].wasteTime; //窗口的结束时间确定,用于下一个客户的初始化
win[i].q.push(num);
}
for (; num <= cnt; ++num) //处理剩余的顾客
{
minTime = INF;
for (int i = 0; i<n; ++i) //找到队列中能最先完成的
{
idx = win[i].q.front();
if (cust[idx].eTime < minTime)
{
minTime = cust[idx].eTime;
pos = i;
}
}
//插入新顾客的时间确定化
cust[num].sTime = win[pos].eTime;
cust[num].eTime = cust[num].sTime + cust[num].wasteTime;
win[pos].eTime += cust[num].wasteTime;
win[pos].q.pop();
win[pos].q.push(num);
}//插入完毕

int hour, minute, query;
while(q--)
{
cin >> query;
if (cust[query].sTime >= 540)
cout << "Sorry" << endl;
else
{
hour = (cust[query].eTime + 8*60)/60;
minute = (cust[query].eTime + 8*60)%60;
if (hour >= 10)
printf("%d:",hour);
else
printf("0%d:",hour);
if (minute>= 10)
printf("%d\n",minute);
else
printf("0%d\n",minute);
}
}
return 0;
}


自己复杂的代码,最后一个测试点段错误

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxcnt = 1005;

4000
const int maxn = 25;
int n, m, cnt;
int cost[maxcnt]; //time needed for each customer

typedef struct node
{
queue<int> q;
int spent;
}LINE;

LINE win[maxn];
int myTurn[maxn];

void init()
{
memset(myTurn, 0, sizeof(myTurn));
for (int i = 0; i < n; ++i)
win[i].spent = 0;
int first = min(n*m, cnt);
for (int i = 1; i <= first; ++i)
(win[(i-1) % n].q).push(i);
}

void calc_time()
{
int minn, smallest;
for (int out = n*m+1; out <= cnt; ++out) //处理还在黄线外的人
{
minn = 0, smallest = INF;
for (int i = 0; i < n; ++i) //选择一个最早能空出来的队列编号minn
{
//发现一个空的队列
if (win[i].q.empty())
{
minn = i;
break;
}
//更新smallest和minn
int predict = win[i].spent + cost[(win[i].q).front()]; //本队列腾出空位的时间
if (predict < smallest)
{
smallest = predict;
minn = i;
}
}
if (win[minn].q.empty() == false) //所选队列不空
{
int who_pop = (win[minn].q).front();
win[minn].q.pop();
myTurn[who_pop] = win[minn].spent; //who_pop的开始时间为之前队列的耗时
win[minn].spent = smallest;
}
win[minn].q.push(out);
}
//黄线外已经处理完
for (int i = 0; i<n; ++i)
{
while(win[i].q.empty() == false)
{
myTurn[win[i].q.front()] = win[i].spent;
win[i].spent += cost[win[i].q.front()];
win[i].q.pop();
}
}
}

int main()
{
int q;
cin >> n >> m >> cnt >> q;
for (int i = 1; i <= cnt; ++i)
cin >> cost[i];
init();
calc_time();
int query, start, hour, minu;
for (int i = 0; i < q; ++i)
{
cin >> query;
start = myTurn[query];
if (start >= 540)
cout << "Sorry" << endl;
else
{
hour = 8, minu = start + cost[query];
hour += (minu/60);
minu %= 60;
if (hour < 10) printf("0%d:", hour);
else printf("%d:",hour);
if (minu < 10) printf("0%d", minu);
else printf("%d",minu);
cout << endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  PAT 队列 模拟