例题6-1 UVA210 Concurrency Simulator(64行AC代码)

紫书刷题进行中,题解系列【GitHub|CSDN

例题6-1 UVA210 Concurrency Simulator(64行AC代码)

题目大意

题目难懂,仔细读题

给定若干个程序,每个程序包含若干条指令,给出每个命令执行所需时间和每个程序的可用时间,模拟指令执行输出相应信息。

五条指令如下:

  • variable = constant:赋值语句,变量variable单字符(26个小写字母,全局共享),初值为0,常量constant为小于100的整数
  • print variable:打印变量值
  • lock:上锁,独占变量资源
  • unlock:解锁,接触独占变量资源
  • end:程序结束

模拟过程中存在两个队列:

  • ready:准备队列,依次执行该队列的程序
  • block:阻塞队列,当已有程序进入lock,其它程序再次遇到lock指令时,需将该程序插入block末尾;当有程序执行unlock后,将block队首加入ready队首

注意1:当目前指令执行所需时间大于剩余可用时间时,也要完整执行

思路分析

主要是队列和双端队列模拟,因此定义如下数据结构,队列q1表示每个程序对应的指令,双端队列qr表示ready队列,存储各个程序的编号;qb为阻塞队列,存储被阻塞的程序编号

queue<string> q1[a[0]]; deque<int> qr; queue<int> qb; // 每个程序对应指令;ready;阻塞

为了处理全局变量,定义map<string, string> vmp;表示变量对应的值,注意给26个小写字母初始化为0

其余只需按照每个命令对应的操作处理即可,仅涉及队列的插入和删除,详见代码注释

注意点

  • 初始化26个字母对应的值为0
  • 访问和出队时注意先判断队列是否为空
  • 测试样例漏了第一行的测试用例个数
  • 当目前指令执行所需时间大于剩余可用时间时,也要完整执行
  • 当遇到阻塞,lock这条指令不算被执行,依旧保留在源程序,一块加入阻塞队列

AC代码(C++11,双端队列,字符串处理)

#include<bits/stdc++.h>
using namespace std;
int T, a[7]; // 测试用例个数,a[0-6]分别表示输入的7个数
string s, ans;
int main() {
    cin >>T;
    for (int i = 0; i < T; i ++) {
        for (int j = 0; j < 7; j ++) scanf("%d", &a[j]);
        getchar(); // 吸收多余字符
        queue<string> q1[a[0]]; deque<int> qr; queue<int> qb; // 每个程序对应指令;ready;阻塞
        for (int j = 0; j < a[0]; j ++) { // n个程序
            while (getline(cin, s) && s != "end") q1[j].push(s);
            qr.push_back(j);
        }
        if (i != 0) puts(""); // 连续输出的空行
        map<string, string> vmp; // 变量对应的值
        bool isLock = false; // 标记是否有锁
        while (!qr.empty()) { // 等待队列非空
            int t = 0, k = qr.front(); qr.pop_front(); // 耗费时间,当前程序编号
            bool isBlock = false; // 标记是否发生阻塞
            while (t < a[6] && !q1[k].empty()) { // 未超时
                s = q1[k].front(); // 取出第一条命令
                int j = s.find('=');
                if (j != string::npos) { // 赋值
                    vmp[s.substr(0,j-1)] = s.substr(j+2);
                    t += a[1]; // 计时
                }
                else {
                    j = s.find(' ');
                    if (j != string::npos) { // 打印输出
                        ans = "0"; // 初始化
                        if (vmp[s.substr(j+1)] != "") ans = vmp[s.substr(j+1)];  
                        printf("%d: %s\n", k+1, ans.c_str()); // print val
                        t += a[2];
                    }
                    else {
                        if (s[0] == 'l') { // lock
                            if (!isLock) { // 未有锁定
                                isLock = true;
                                t += a[3]; // 时间增加
                            }
                            else { // 已有锁定
                                qb.push(k); // 加入阻塞队列尾部
                                isBlock = true;
                                break; // 直接退出,忽略其它剩余时间
                            }
                        }
                        else if (s[0] == 'u') { // unlock
                            isLock = false; // 标记未锁定
                            if (!qb.empty()) { // 阻塞非空
                                qr.push_front(qb.front()); // 阻塞头部加入ready头部
                                qb.pop();
                            }
                            t += a[4];
                        }
                    }
                }
                q1[k].pop(); // 确保阻塞时lock命令不会被删除
            }
            if (!q1[k].empty() && !isBlock) qr.push_back(k); // 非空再次加入等待队列尾部
        }
    }
    return 0;
}
发布了128 篇原创文章 · 获赞 87 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40738840/article/details/104271115
今日推荐