大家好,我是小黄呀。
题目大意
题目给出n个程序,其中每个程序包含若干条指令,每条指令执行所需时钟周期,给出每个程序拥有的总共时钟周期数,模拟出程序执行的过程,输出相应的信息。
五条指令如下:
var = constant
:赋值,其中var
为单个小写字母表示,初始为0,是全局变量。constant
为小于100的非负整数,是常数。print var:
打印lock
:上锁,独占资源。unlock
:解锁end
:程序结束
程序模拟过程中存在两个队列:
rq
:等待队列,按此队列依次执行rb
:阻止队列,当程序1执行lock
时,若程序2再次执行lock
,则将程序2放入rb
队列中,直到程序执行unlock
后,再将rb
队列的队首插入到rq
队列队首
思路分析
由于lock和unlock指令的具体执行过程,违反了基本队列的规则,具体有两种方法。
- 自定义一个支持“首部插入”的队列
- 利用STL中的双端队列
deque
具体代码及分析
- 方法一:自定义一个支持“首部插入”的队列
template<class T1,class T2> struct pair
:pair可以将两个类合二为一,成为一组数据,相当于一个结构体。更多详细内容
#include<bits/stdc++.h>
#define CLOSE() ios::sync_with_stdio(false)
#define CLEAR(a,b) memset(a,b,sizeof(a))
#define IN() freopen("in.txt","r",stdin)
#define OUT() freopen("out.txt","w",stdout)
using namespace std;
const int maxn=1e3;
using LL=long long;
using UI=unsigned int ;
//-----------------------------------------
vector<vector<string> >prog;
vector<pair<int,int> > rf;
int readyq[maxn],rrear,rfront;
int blocked[maxn],brear,bfront;
int main()
{
#ifdef _DEBUG
IN();
OUT();
#endif // _DEBUG
int T;
scanf("%d",&T);
while(T--)
{
int n,time[5],qutm;//n个程序,每条指令所需的时钟周期,总时钟周期
scanf("%d",&n);
for(int i=0;i<5;++i)
scanf("%d",&time[i]);
scanf("%d",&qutm);
getchar();
prog.clear();
rf.clear();
CLEAR(readyq,0);
rrear=rfront=0;
for(int i=0;i<n;i++)//存入每个程序的指令
{
readyq[rfront++]=i;
string s;
while(getline(cin,s))
{
prog.push_back(vector<string>());
rf.push_back(make_pair(0,0));
prog[i].push_back(s);
if(s=="end")break;
}
}
CLEAR(blocked,0);
brear=bfront=0;
map<char,int> vari;
bool lock=false;
while(rrear!=rfront)//准备队列非空
{
int nowprog = readyq[rrear++];
readyq[rfront++] = nowprog;
//printf("now = %d\n", nowprog+1);
int t = qutm;
while (t > 0) //在时间范围内
{
string inst = prog[nowprog][rf[nowprog].first++];
int p = inst.find('='), p2 = inst.find("print");
if (inst == "end") {
rfront--;
break;
}
else if (p != -1) {
vari[inst[p - 2]] = atoi(inst.substr(p + 2).c_str());
t -= time[0];
}
else if (p2 != -1) {
char va = inst[p2 + 6];
printf("%d: %d\n", nowprog + 1, vari[va]);
t -= time[1];
}
else if (inst == "lock") {
if (!lock) {
lock = true;
t -= time[2];
}
else {
rfront--;
blocked[bfront++] = nowprog;
rf[nowprog].first--;
break;
}
}
else {
t -= time[3];
lock = false;
if (brear != bfront) {
readyq[--rrear] = blocked[brear++];
}
}
}
}
if (T) puts("");
}
return 0;
}
- 方法二:STL中的双端队列
deque
(先贴的最简洁的,但不好懂)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3;
int T,a[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;//阻止队列
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();//t为已消耗的时长,k为当前程序的编号
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());
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());//阻止队列首部加入等待队列首部
qb.pop();
}
t+=a[4];
}
}
}
q1[k].pop();
}
if(!q1[k].empty()&&isBlock)//再次加入等待队列等待
{
qr.push_back(k);
}
}
}
return 0;
}