传送门
写这道题的时候表示看了很久都没看懂到底是什么意思。。最后还是看了大佬的题解才明白题意http://blog.csdn.net/qq_40738840/article/details/104271115
在我研究了很久大佬的代码后我终于看懂题意了
题目大概意思就是:
要我们来模拟并行,即只能有一个运行态其余都是等待状态。
输入n个程序,每个程序有一些指令,指令分为五种,每种程序都要花相应的时间,一个程序在运行态的时候他执行所有指令所花的时间不能超过Q即配额。如果遇到block时别的程序已经执行过block,那么该程序就进入阻塞队列,不会执行下面的语句,直到遇到unlock才会将阻塞态队首放入等待态队首,然后按照样例模拟一下就明白了。
这里再解释一下样例(题目要求的是多组样例,但测试样例并没有体现这一点,所以在写代码的时候要注意)
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
由于总配额是1,而五条指令所花的时间也是1,那么就是说每个程序每次只能执行一条语句,如果遇到block之前已经有程序执行过block那么就直接跳出执行下一个程序,所以说刚开始的时候执行程序的顺序是1 2 3,第一轮结束a = 3,所以在第二轮运行的时候输出a为3,依次类推,如果还看不懂的话就看代码和注释吧。
这道题就是采用双端队列与队列的结合,首先定义三个队列
queue<string>q1[a[0]];//每个程序的所有指令
queue<int>qb;//阻塞队列
deque<int>qr;//等待队列
这里的a[0]表示有n个程序,第i个程序的所有指令都放入该程序的队列中。
注意我们要设置两个标记:
1.isblock:标记是否遇到过block,如果没有遇到过就设置为false,如果遇到过就设置为true,将该程序插入阻塞队列
2.isBlock:标记这个程序是否被阻塞,如果block为true就把isBlock标记为true,否则为false
那么如果isBlock为false并且该程序的指令还没有执行完,那么我们就还要将该程序放入等待队列队首。
同时在访问前要判断队列是否为空,格式也有一定要求,每个样例后面都要有一个空行。
完整代码及注释:
#include <iostream>
#include <queue>
#include <deque>
#include <string>
#include <cstring>
#include <map>
using namespace std;
int a[7];//每个样例输入的七个数,分别代表n个程序,t1-t5指令所花时间,每个运行态的配额Q
string s;//存储指令
string ans;//存储变量值
int main()
{
int T;//测试样例个数
cin >> T;
for(int j = 0 ; j < T; j++)
{
for(int i = 0 ; i < 7; i++)
{
cin >> a[i];
}
getchar();
queue<string>q1[a[0]];//每个程序的所有指令
queue<int>qb;//阻塞队列
deque<int>qr;//等待队列
for(int i = 0 ; i < a[0]; i++)//输入n个程序的指令
{
while(getline(cin,s) && s != "end")//第i个程序的指令
{
q1[i].push(s);
}
qr.push_back(i);//插入等待队列
}
if(j != 0)
{
cout << endl;
}
map<string,string>mp;//存储赋值操作语句
bool isblock = false;//标记是否有锁
while(!qr.empty())//等待队列不为空
{
int t = 0;//程序执行的时间
int k = qr.front();//取出等待队列队首,执行队首程序
qr.pop_front();
bool isBlock = false;//标记是否发生阻塞
while(t < a[6]/*该程序未超时*/ && !q1[k].empty()/*该程序未执行完*/)
{
s = q1[k].front();//取出指令
int i = s.find('=');
if(i != string::npos)//如果是赋值指令
{
mp[s.substr(0,i - 1)] = s.substr(i + 2);//赋值
t += a[1];//计时
}
else//如果不是赋值操作
{
i = s.find(' ');
if(i != string::npos)//打印输出
{
ans = "0";
if(mp[s.substr(i + 1)] != "")//如果该字母的值不为空
{
ans = mp[s.substr(i + 1)];
}
t += a[2];
cout << k + 1 << ": " << ans.c_str() << endl;
}
else //如果遇到阻塞
{
if(s[0] == 'l')
{
if(!isblock)//如果之前没有遇到过阻塞
{
isblock = true;
t += a[3];
}
else//如果之前遇到过
{
qb.push(k);//放入阻塞队列队尾
isBlock = true;
break;
}
}
else if(s[0] == 'u')//遇到解锁
{
isblock = false;//解锁
if(!qb.empty())//如果阻塞队列非空
{
qr.push_front(qb.front());//阻塞队列队首插入等待队列队首
qb.pop();
}
t += a[4];
}
}
}
q1[k].pop();
}
if(!q1[k].empty() && !isBlock)
{
qr.push_back(k);//如果非空再次加入队列尾部
}
}
}
return 0;
}