题目链接:https://vjudge.net/problem/UVA-822

翻译摘自:《算法禁赛入门经典》

题目大意

  你的任务是模拟一个客户中心运作情况。客服请求一共有n(1 ≤ n ≤ 20)种主题,每种主 题用 5 个整数描述:tid, num, t0, t, dt,其中 tid 为主题的唯一标识符,num为该主题的请求个 数,t0 为第一个请求的时刻,t 为处理一个请求的时间,dt 为相邻两个请求之间的间隔(为了简化情况,假定同一个主题的请求按照相同的间隔到达)。
  客户中心有m(1 ≤ m ≤ 5)个客服,每个客服用至少 3 个整数描述:pid, k, tid1 , tid2 , …, tidk,表示一个标识符为 pid 的人可以处理 k 种主题的请求,按照优先级从大到小依次为 tid1 , tid2 , …, tidk。当一个人有空时,他会按照优先级顺序找到第一个可以处理的请求。如果有多 个人同时选中了某个请求,上次开始处理请求的时间早的人优先;如果有并列,再输入列表前面的优先。输出最后一个请求处理完毕的时刻。

分析

  这道题我是崩溃的,首先 udebug 上的程序跑出来的数据是错误的,我在网上找了一份 AC 代码,和《算法禁赛入门经典》的 AC 代码对拍,两个跑出来还是不一样。
  题目是好题,但不推荐做,因为数据实在太马虎了。

代码如下

 #include <bits/stdc++.h>
using namespace std; #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define Rep(i,n) for (int i = 0; i < (int)(n); ++i)
#define For(i,s,t) for (int i = (int)(s); i <= (int)(t); ++i)
#define rFor(i,t,s) for (int i = (int)(t); i >= (int)(s); --i)
#define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
#define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) #define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl #define LOWBIT(x) ((x)&(-x)) #define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define UNIQUE(x) x.erase(unique(x.begin(), x.end()), x.end())
#define REMOVE(x, c) x.erase(remove(x.begin(), x.end(), c), x.end()); // 删去 x 中所有 c
#define TOLOWER(x) transform(x.begin(), x.end(), x.begin(),::tolower);
#define TOUPPER(x) transform(x.begin(), x.end(), x.begin(),::toupper); #define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,0x3f,sizeof(a))
#define msM(a) memset(a,-1,sizeof(a)) #define MP make_pair
#define PB push_back
#define ft first
#define sd second template<typename T1, typename T2>
istream &operator>>(istream &in, pair<T1, T2> &p) {
in >> p.first >> p.second;
return in;
} template<typename T>
istream &operator>>(istream &in, vector<T> &v) {
for (auto &x: v)
in >> x;
return in;
} template<typename T>
ostream &operator<<(ostream &out, vector<T> &v) {
Rep(i, v.size()) out << v[i] << " \n"[i == v.size() - ];
return out;
} template<typename T1, typename T2>
ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
out << "[" << p.first << ", " << p.second << "]" << "\n";
return out;
} inline int gc(){
static const int BUF = 1e7;
static char buf[BUF], *bg = buf + BUF, *ed = bg; if(bg == ed) fread(bg = buf, , BUF, stdin);
return *bg++;
} inline int ri(){
int x = , f = , c = gc();
for(; c<||c>; f = c=='-'?-:f, c=gc());
for(; c>&&c<; x = x* + c - , c=gc());
return x*f;
} template<class T>
inline string toString(T x) {
ostringstream sout;
sout << x;
return sout.str();
} inline int toInt(string s) {
int v;
istringstream sin(s);
sin >> v;
return v;
} //min <= aim <= max
template<typename T>
inline bool BETWEEN(const T aim, const T min, const T max) {
return min <= aim && aim <= max;
} typedef unsigned int uI;
typedef long long LL;
typedef unsigned long long uLL;
typedef vector< int > VI;
typedef vector< bool > VB;
typedef vector< char > VC;
typedef vector< double > VD;
typedef vector< string > VS;
typedef vector< LL > VL;
typedef vector< VI > VVI;
typedef vector< VB > VVB;
typedef vector< VS > VVS;
typedef vector< VL > VVL;
typedef vector< VVI > VVVI;
typedef vector< VVL > VVVL;
typedef pair< int, int > PII;
typedef pair< LL, LL > PLL;
typedef pair< int, string > PIS;
typedef pair< string, int > PSI;
typedef pair< string, string > PSS;
typedef pair< double, double > PDD;
typedef vector< PII > VPII;
typedef vector< PLL > VPLL;
typedef vector< VPII > VVPII;
typedef vector< VPLL > VVPLL;
typedef vector< VS > VVS;
typedef map< int, int > MII;
typedef unordered_map< int, int > uMII;
typedef map< LL, LL > MLL;
typedef map< string, int > MSI;
typedef map< int, string > MIS;
typedef multiset< int > mSI;
typedef set< int > SI;
typedef stack< int > SKI;
typedef deque< int > DQI;
typedef queue< int > QI;
typedef priority_queue< int > PQIMax;
typedef priority_queue< int, VI, greater< int > > PQIMin;
const double EPS = 1e-;
const LL inf = 0x7fffffff;
const LL infLL = 0x7fffffffffffffffLL;
const LL mod = 1e9 + ;
const int maxN = 1e5 + ;
const LL ONE = ;
const LL evenBits = 0xaaaaaaaaaaaaaaaa;
const LL oddBits = 0x5555555555555555; struct Event{
int id; // 活动对应实体在数组中的序号
int time;
bool isRorC; // 是请求到达还是客服空闲事件 Event(int x, int y, bool z) {
time = x;
id = y;
isRorC = z;
} bool operator< (const Event &x) const {
return time > x.time;
}
}; struct ReqInfo {
int tid; // 请求id
int idx; // 数组下标id
int num; // 请求数量
int t0; // 第一个请求到达时间
int t; // 请求处理耗时
int dt; // 两个相邻请求之间的到达间隔
}; istream& operator>> (istream& in, ReqInfo &x) {
in >> x.tid >> x.num >> x.t0 >> x.t >> x.dt;
return in;
} struct StaffInfo {
int pid; // 职员id
int idx; // 数组下标id
int k; // 职员所能处理的请求数量
VI tids; // 所能处理的请求id,优先级从大到小
int last; // 上次开始处理请求的时间 bool operator< (const StaffInfo &x) const {
return last < x.last || last == x.last && idx < x.idx;
}
}; istream& operator>> (istream& in, StaffInfo &x) {
in >> x.pid >> x.k;
x.tids.resize(x.k);
Rep(i, x.k) in >> x.tids[i];
return in;
} int N, M, T, ans;
vector< ReqInfo > reqs;
vector< StaffInfo > staffs; priority_queue< Event > waitQ; // 等待队列,按时间升序
mSI mInQ; // 当前队列中的所有任务
SI freeStaffs; // 空闲员工集合 bool readInfoAndGenerateEvent() {
MII ridToIdx; // 存请求id与实际存的数组下标的对应关系 cin >> N;
if(!N) return false;
reqs.resize(N);
Rep(i, N) {
auto &r = reqs[i]; cin >> r;
ridToIdx[r.tid] = i;
r.idx = i; // 把请求id变成数组下标,方便写代码 Rep(j, r.num) waitQ.push(Event(r.t0 + r.dt * j, i, true)); // 请求到达活动
} cin >> M;
staffs.resize(M);
Rep(i, M) {
auto &sf = staffs[i]; cin >> sf;
Rep(j, sf.k) sf.tids[j] = ridToIdx[sf.tids[j]];
sf.idx = i; // 把客服id变成数组下标,方便写代码
sf.last = ; waitQ.push(Event(, i, false)); // 客服空闲活动
} return true;
} struct StaffCompByIdx {
bool operator() (int x, int y) const {
return staffs[x] < staffs[y];
}
}; void solve() {
int nowTime = waitQ.top().time;
ans = nowTime; while(!waitQ.empty() && nowTime == waitQ.top().time) { // 把到达的活动全取出来
const Event &e = waitQ.top(); if(e.isRorC) mInQ.insert(e.id); // 有新请求到达了
else freeStaffs.insert(e.id); // 有客服空闲了 waitQ.pop();
} // 分配任务
while(!mInQ.empty() && !freeStaffs.empty()) { // 任务队列里有请求并且有员工空闲
vector< set< int, StaffCompByIdx > > req_staffs(N); // 每种请求可供受理的员工集合
bool canAssign = false; // 是否能分配任务 for(auto &i : freeStaffs) { // 枚举每个空闲客服
auto &fs = staffs[i]; Rep(j, fs.k) { // 依次遍历每一项可处理的请求
int tid = fs.tids[j]; if(mInQ.find(tid) == mInQ.end()) continue;
canAssign = true; req_staffs[tid].insert(fs.idx); // 第一个可处理的请求
break; // 直接退出即可,后面优先级的请求等这轮循环没分配到再进入下一轮分配
}
} if(!canAssign) break; // 没人分配到工作就退出 Rep(i, N) { // 枚举请求号
auto &rs = req_staffs[i]; while(mInQ.find(i) != mInQ.end() && !rs.empty()) { // 任务队列中有这个请求并且有员工能处理这个请求
mInQ.erase(mInQ.find(i)); int pid = *(rs.begin()); // 排名第一的能处理 i 号请求的员工 id,给他分配任务
auto &sf = staffs[pid]; sf.last = nowTime;
waitQ.push(Event(nowTime + reqs[i].t, sf.idx, false)); // 下一个客服空闲请求
freeStaffs.erase(sf.idx);
rs.erase(pid);
}
}
}
} int main() {
//freopen("MyOutput.txt","w",stdout);
//freopen("input.txt","r",stdin);
//INIT();
while(readInfoAndGenerateEvent()) {
ans = ;
freeStaffs.clear(); while(!waitQ.empty()) solve();
printf("Scenario %d: All requests are serviced within %d minutes.\n", ++T, ans);
}
return ;
}

UVA 822 Queue and A的更多相关文章

  1. UVA Team Queue

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013840081/article/details/26180081 题目例如以下: Team Qu ...

  2. UVa——540Team Queue(STL练习map、queue数组的综合使用)

    Team Queue Time Limit:                                                        3000MS                 ...

  3. The Summer Training Summary-- the first

    The Summer Training Summary-- the first A - vector的使用 UVa 101 关于vector 的几个注意点 vector p p.push_back() ...

  4. UVA.540 Team Queue (队列)

    UVA.540 Team Queue (队列) 题意分析 有t个团队正在排队,每次来一个新人的时候,他可以插入到他最后一个队友的身后,如果没有他的队友,那么他只能插入到队伍的最后.题目中包含以下操作: ...

  5. uva 540 - Team Queue(插队队列)

    首发:https://mp.csdn.net/mdeditor/80294426 例题5-6 团体队列(Team Queue,UVa540) 有t个团队的人正在排一个长队.每次新来一个人时,如果他有队 ...

  6. Trees on the level UVA - 122 复习二叉树建立过程,bfs,queue,strchr,sscanf的使用。

    Trees are fundamental in many branches of computer science (Pun definitely intended). Current state- ...

  7. UVA 540 Team Queue(模拟+队列)

    题目代号:UVA 540 题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page ...

  8. UVA 133 The Dole Queue

    The Dole Queue 题解: 这里写一个走多少步,返回位置的函数真的很重要,并且,把顺时针和逆时针写到了一起,也真的很厉害,需要学习 代码: #include<stdio.h> # ...

  9. UVa 12100 (模拟) Printer Queue

    用一个队列模拟,还有一个数组cnt记录9个优先级的任务的数量,每次找到当前最大优先级的任务然后出队,并及时更新cnt数组. #include <iostream> #include < ...

随机推荐

  1. Linux ftp安装

    ftp安装部分,操作步骤如下: 可以使用yum命令直接安装ftp # yum install vsftpd ftp服务的开启与关闭命令: 开启:# /bin/systemctl start vsftp ...

  2. jQuery基础教程之is()方法和has() 方法

    is()方法 —— 用于筛选 语法: jQueryObject.is( expr )返回值: is()函数的返回值为Boolean类型.true或者false.只要其中至少有一个元素符合给定的表达式就 ...

  3. upc组队赛16 Melody【签到水】

    Melody 题目描述 YellowStar is versatile. One day he writes a melody A = [A1, ..., AN ], and he has a sta ...

  4. selenium:Xpath定位详解

    xpath定位在业界被戏称为元素定位的"屠龙宝刀",宝刀在手,武林我有.现在我们就来详解xpath定位方法. 一.xpath通过元素属性定位 xpath可以通过元素的属性来定位,如 ...

  5. PAT甲级【2019年3月考题】——A1156 SexyPrimes【20】

    Sexy primes are pairs of primes of the form (p, p+6), so-named since “sex” is the Latin word for “si ...

  6. 关于<a></a>标签里嵌套<a></a>标签的bug

    当你用一个<a></a>标签时,在<a>标签中再插入一个<a></a>,此时,你会发现外面的<a>标签会重复出现,且有点混乱.找 ...

  7. 七、hibernate的事务使用

    hibernate中事务隔离级别 1:读未提交 2:读已提交 4:可重复读 8:可串行化 hibernate事务使用 在核心配置文件中配置事务隔离级别 <property name=" ...

  8. Springboot整合Hikari数据库连接池,密码加密

    1.application.yml配置 spring: datasource: jdbcUrl: jdbc:mysql://127.0.0.1:3306/jby?serverTimezone=UTC& ...

  9. selectDOM操作详解-select option详细解释

    首先从一个面试题来讲,我最近在做前端面试题,题目如下: 完成函数showlmg(),要求能够动态根据下拉列表的选项变化,更新图片的显示<body><script type=" ...

  10. Java 枚举(enum)详解

    概念: Java1.5发行版本中增加了新的引用类型--枚举类型(enum type).枚举类型是指由一组固定的常量组成合法值的类型.在Java虚拟机中,枚举类在进行编译时会转变成普通的Java类. 创 ...