此题巨坑,慎入。
本人按紫书上所给思路实现,由于时间限制在一天内,分钟数小于1440,故每次分钟数増一也可保证算法所用时间不超时。此种方法无需优先队列。
1.已到达的请求移出topics,存储在waitingrequests当中。
2.对于每个客服,按序遍历其熟悉的工作,如果遇到其熟悉的工作在waitingrequests当中,则停止遍历,并将其放入chosen中,每个客服只选了一个请求。
3.若chosen.size()>0,置change=1。对于chosen中的每个工作,其可能对应有多个客服的请求,则客服lasttime小的优先,如一致,则在输入中靠前的优先。
4.若change=1,说明该轮有工作被客服成功选中,为避免客服虽选了请求但未成功选上而导致客服本可以选其他请求而最终没有选,我们返回2,再进行一轮选择。否则,执行5。
5.++usedtime,并对于每一个忙的客服,–remaintime。
6.若客服正忙或waitingrequests非空或topics非空,返回1;否则输出结果。
注意:本题UVa上的数据较弱,对于一些较复杂的数据,其他人给出的答案不同,依然可以AC
#include <vector>
#include <map>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstdio>
#include <sstream>
#include<iostream>
#include<iomanip>
#include<stack>
#include<iterator>
#include<utility>
#include<unordered_map>
#include<queue>
#include<cstring>
#include <list>
#include<deque>
#include <string>
using namespace std;
typedef struct request
{
int tid;
int t;
friend bool operator<(const request&a,const request&b)
{
if(a.tid<b.tid||a.tid==b.tid&&a.t<b.t)
return true;
else
return false;
}
}request;
typedef struct subject
{
request obj;
int num;
int t0;
int dt;
}subject;
typedef struct staff
{
int k;
vector<int>tid;
int remaintime;
int lasttime;
int ith;
}staff;
int main()
{
int num;
int cnt=1;
while(cin>>num&&num!=0)
{
vector<subject>topics;
map<request,int>waitingrequests;
map<int,staff>staffs;//键值为pid
int usedtime=0;
while(num-->0)
{
subject tmp;
cin>>tmp.obj.tid>>tmp.num>>tmp.t0>>tmp.obj.t>>tmp.dt;
topics.push_back(std::move(tmp));
}
int staffnum;
cin>>staffnum;
while(staffnum-->0)
{
int pid;
staff tmp;
cin>>pid;
cin>>tmp.k;
int k=tmp.k;
tmp.ith=staffnum;
while(k-->0)
{
int pri;
cin>>pri;
tmp.tid.push_back(std::move(pri));
}
tmp.remaintime=0;
tmp.lasttime=0;
staffs[pid]=std::move(tmp);
}
bool isbusy;//如为1则有客服在处理请求
do
{
isbusy=0;
for(vector<subject>::iterator iter=topics.begin();iter!=topics.end();)
{
if(iter->num>0)
{
if(iter->t0<=usedtime&&(usedtime-iter->t0)%iter->dt==0)
{
--iter->num;
++waitingrequests[iter->obj];
}
}
if(iter->num==0)
{
iter=topics.erase(iter);
}
else
++iter;
}
bool change;
do
{
change=0;
map<int,vector<int>>chosen;//为tid到获取该请求的客服的pid的映射
map<int,int>timemap;
for(auto iter=staffs.begin();iter!=staffs.end();++iter)//寻找第一个可处理的请求
{
if(iter->second.remaintime==0)
{
bool ischosen=0;
for(auto elem:iter->second.tid)
{
for(auto reqit=waitingrequests.begin();reqit!=waitingrequests.end();++reqit)
{
if(reqit->first.tid==elem)
{
ischosen=1;
chosen[elem].push_back(iter->first);
timemap[elem]=reqit->first.t;
--reqit->second;
if(reqit->second==0)
waitingrequests.erase(reqit);
break;
}
}
if(ischosen)
break;
}
}
}
for(auto iter=chosen.begin();iter!=chosen.end();++iter)
{
int firststaffpid=iter->second[0];
for(int i=1;i<iter->second.size();++i)
{
int currentpid=iter->second[i];
if(staffs[firststaffpid].lasttime>staffs[currentpid].lasttime||
(staffs[firststaffpid].ith<staffs[currentpid].ith&&staffs[firststaffpid].lasttime==staffs[currentpid].lasttime))
{
firststaffpid=currentpid;
}
}
staffs[firststaffpid].remaintime=timemap[iter->first];
staffs[firststaffpid].lasttime=usedtime;
change=1;
}
}while(change==1);
++usedtime;
for(auto iter=staffs.begin();iter!=staffs.end();++iter)
{
if(iter->second.remaintime>0)
--iter->second.remaintime;
if(iter->second.remaintime>0)
isbusy=1;
}
} while (isbusy==1||waitingrequests.size()>0||topics.size()>0);
cout<<"Scenario "<<cnt++<<": All requests are serviced within "<<usedtime<<" minutes."<<endl;
}
}