并行程序模拟(ACM/ICPC World Finals 1991, UVa210)

原题链接:https://vjudge.net/problem/UVA-210


并行程序模拟题意

题目的要求是要我们模拟计算机并行程序的运行。每个程序由若干语句组成,在该题中总共有5种语句,每种语句有其相应的单位运行时间。var = constant(赋值);print var(打印);lock;unlock;end(结束)。

五种语句只有 var = constant( 0

若有n个程序,则按照次序依次运行Q个单位时间(quatum,配额),每次至少执行一条语句。在上述过程中若一个程序有剩余语句未执行完,则插入一个等待队列 尾部。类似于TDM时分复用,每一个程序在不同时间的占用频带宽度

但由于 lockunlock 的作用特殊,我们需要一个队首和队尾都能插入元素的队列,即STL中的双端队列deque——等待队列lockunlock 成对出现,且 lock 只能被执行一次(在对应的unlock未执行时)。lock 执行失败的程序会立即(未消耗配额)放入阻止队列unlock运行后 阻止队列 队首进入 等待队列 队首。


注意点

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

测试数据

1
3 1 1 1 1 1 1
a = 4
print a
lock
b = 9
print b
unlock
print b
end
a = 3
print a
lock
b = 8
print b
unlock
print b
end
b = 5
a = 17
print a
print b
lock
b = 21
print b
unlock
print b
end


样例输出

1: 3
2: 3
3: 17
3: 9
1: 9
1: 9
2: 8
2: 8
3: 21
3: 21


代码示例

#include 
#include 
#include 
#include 
using namespace std;
int T, a[7]; // a[0]-a[6]分别表示n,t1,t2,t3,t4,t5,Q
string s, ans;
int main()
{
    cin >> T; //测试数据组数
    for (int i = 0; i < T; i++)
    {
        for (int j = 0; j < 7; j++)
            cin >> a[j];
        getchar();                     // 吸收多余字符,回车
        queue<string> q1[a[0]];        //存储数据再操作
        deque<int> qr;                 //双端队列 等待对列-ready
        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("");            //不然提交提示 "Presentation Error"
        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()) //a[6]即Q份额
            {                                  // 未超时
                s = q1[k].front();             // 取出第一条命令
                int j = s.find('=');           //未找到返回string::npos
                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(); // 删除已执行的命令,由于前面的break,未执行的lock不会被删除 
            }
            if (!q1[k].empty() && !isBlock)
                qr.push_back(k); // 非空再次加入等待队列尾部
        }
    }
    return 0;
}


你可能感兴趣的:(算法竞赛,算法)