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);
    }
} 

 

posted @ 2019-07-02 14:52  ellenxx  阅读(1710)  评论(5编辑  收藏  举报