ccf——201903-4 消息传递接口
题目解读:
老师给了T份样例,有n个进程,这n个进程之间可以receive接收和send发送消息(如R1,S2....)。R,S即接收和发送的进程号要对应起来,例如R1必须与S0配对。
当开始时,初始所有的进程为准备就绪的状态,然后开始从第一个进程的第一个消息A开始,如果A消息要和第x号进程进行R 或 S,就看X号进程队列的头部B是否能和A配对,如果能配对,就继续第一个进程的下一个消息;如果不能,就先处理X号进程,看B要和哪一个进程配对,配对好了就继续X号里的下一个消息,直到能找到和A配对的消息,这是一个递归的过程。当然,在这过程中,如果发现有进程处于一直等待状态,或配对过程中发现某一方进程已经为空,这份样例的代码就处于“锁死”了。
知识点:
queue
#include<queue> //头文件 queue<int> test; //初始化一个int型的队列名为test test.empty() ; //查看队列是否为空 test.size(); //返回队列大小 test.front(); //返回队列下一个元素 test.back(); // 返回队列最后一个元素 test.push(); //添加一个元素 test.pop(); //删除队列下一个元素 test.emplace(); //构造和插入元素 test.swap(); //交换内容
istringstream:
istringstream类用于执行C++风格的串流的输入操作、
这里用于将字符串从空格处分开
atoi():
C库函数,将数值型字符转化为数值
c_str()
通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式,这样就可以在C库函数里使用了
代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<sstream> #include<queue> using namespace std; const int MAXN=10005; //每个消息的结构 struct Mes{ char flag;//接收消息 int target;//目标进程 }; //进程 struct Pro{ queue<Mes> task; }; Pro pro[MAXN];//进程数组 int wait[MAXN];//进程状态 int receiveM(int from,int to); int sendM(int from,int to); int exe(int now) { if(wait[now]==1) return -1;//判断当前进程是否处于等待 if(pro[now].task.empty()) return 0;//队列为空,则表示该进程消息已经处理完毕 Mes cur=pro[now].task.front(); if(cur.flag=='R') { wait[now]=1;//现在该进程在进行任务,其他消息只能等待 if(receiveM(now,cur.target)==-1) return -1; //消息接收成功 pro[now].task.pop();//消息处理成功,从消息队列里移除 wait[now]=0;//消息处理完毕,进程继续准备 if(exe(now)==-1) return -1;//处理下一个消息 return 0; } else if(cur.flag=='S') { wait[now]=1; if(sendM(now,cur.target)==-1) return -1; //成功配对 wait[now]=0; pro[now].task.pop(); if(exe(now)==-1) return -1; return 0; } } int receiveM(int from,int to) { if(wait[to]==1) return -1; if(pro[to].task.empty()) return -1;//如果该进程已经没有消息了,接不会执行 Mes cur=pro[to].task.front(); if(cur.flag=='R') { wait[to]=1; if(receiveM(to,cur.target)==-1) return -1;//递归处理下一个消息 wait[to]=0; pro[to].task.pop(); if(receiveM(from,to)==0) return 0;//递归判断之前的消息是否可以处理 return -1; } else if(cur.flag=='S') { if(from==cur.target){ pro[to].task.pop(); return 0; } //不能配对成功 wait[to] =1; if(sendM(to,cur.target)==-1) return -1; wait[to]=0; pro[to].task.pop(); if(receiveM(from,to)==0) return 0; return -1; } } int sendM(int from,int to) { if(wait[to]==1) return -1; if(pro[to].task.empty()) return -1; Mes cur=pro[to].task.front(); if(cur.flag=='R') { if(from==cur.target) { pro[to].task.pop(); return 0; } wait[to]=1; if(receiveM(to,cur.target)==-1) return -1; wait[to]=0; pro[to].task.pop(); if(sendM(from,to)==0) return 0; return -1; } else if(cur.flag=='S') { wait[to]=1; if(sendM(to,cur.target)==-1) return -1; wait[to]=0; pro[to].task.pop(); if(sendM(from,to)==0) return 0; return -1; } } int T,n; int main() { scanf("%d %d",&T,&n); getchar();//回车 for(int i=0;i<T;i++) { memset(wait,0,sizeof(wait));//初始化进程状态 for(int j=0;j<n;j++) { //初始化每个进程的消息队列 while(!pro[j].task.empty()) pro[j].task.pop(); } for(int j=0;j<n;j++) { //处理输入 string line; getline(cin,line); istringstream ss(line); string tmp; while(ss>>tmp){ Mes mes; mes.flag=tmp[0];//获取R,S mes.target=atoi(tmp.c_str()+1);//获取目标进程 pro[j].task.push(mes); //加入消息队列 } } int flag=0; for(int j=0;j<n;j++) { if(!pro[j].task.empty()) { if(exe(j)==-1){ //锁死 flag=1; break; } } } printf("%d\n",flag); } }