CCF 201903-4 消息传递接口

在这里插入图片描述
题记
这道题最关键就是要发现每次配对都是发生在每个进程的最开始,还有一点比较绕的是每个进程必须完全执行完一次才能进入下一次任务,但是对方进程不一定马上回应,可以执行完另一个任务再响应,但是总的来说配对还是发生在最开头。比如有三个进程a,b,c。a发一个任务等b回应,b第一个任务是和c进行交互,完成后b第一个就变成了对a的回应。所以每次对各个进程第一个取出来,看看它们之间是否存在可以配对的,如果没有,说明存在死锁或者所有任务都完成了。

#include <iostream>
#include <string>
#include <queue>
#include <sstream>
using namespace std;

const int Maxn=1e4+10;

//输入
int T,n;

struct node {
    int type;//R-0,S-1
    int need;//需要need号进程回应
};
queue<node> q[Maxn];

int findnum(string& str){
    int n=str.size(),ans=0;
    for(int i=1;i<n;i++)
        ans=ans*10+str[i]-'0';
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>T>>n;
    cin.get();//吃掉换行符
    while(T--){
        for(int i=0;i<n;i++){
            string line;
            string command;
            getline(cin,line);
            stringstream ss(line);
            while(ss>>command){
                node temp;
                temp.type=command[0]-'R';
                temp.need=findnum(command);
                q[i].push(temp);
            }
        }

        int cnt;
        bool flag=true;
        while(1){
            //对每一个进程的第一个遍历看看有没有配对的
            cnt=0;//遍历一趟成功配对数.遍历完还是0一定有死锁
            for(int i=0;i<n;i++){
                if(q[i].empty())//这个进程的命令执行完了,接着下一个
                    continue;
                node u=q[i].front();
                if(q[u.need].empty()){//需要回应的进程已经空了,一定有死锁
                    flag=false;
                    break;
                }
                else{
                    node v=q[u.need].front();
                    if(v.type^u.type&&v.need==i){
                        q[i].pop();
                        q[u.need].pop();
                        i--,cnt++;//i号进程配对成功一个,接着对i号配对.紧着一个进程做
                    }
                    else
                        continue;
                }
            }
            if(!flag||!cnt)
                break;
        }
        for(int i=0;i<n;i++)
            if(!q[i].empty()){
                flag=false;
                cout<<"1"<<endl;
                break;
            }
        if(flag)
            cout<<"0"<<endl;
        for(int i=0;i<n;i++)
            q[i]=queue<node>();//清空每个队列
    }
    return 0;
}

样例输入1

3 2
R1 S1
S0 R0
R1 S1
R0 S0
R1 R1 R1 R1 S1 S1 S1 S1
S0 S0 S0 S0 R0 R0 R0 R0

样例输入2

2 3
R1 S1
R2 S0 R0 S2
S1 R1
R1
R2 S0 R0
S1 R1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值