CCF 201903-4 试题名称:消息传递接口

题目描述
在这里插入图片描述
    参加了这场认证,及格分都没拿到,最近准备二战。。
    当时感觉这道题写得挺有把握的,结果只拿了60分,原因我就不说了,反正菜就对了。
    下面就来分享下做题思路:
    其实实现思路非常简单,只是稍微有点绕。当你看测试样例的时候,其实你脑袋里就在模拟消息传递的过程。其实这道题也就是模拟那个过程,没有什么独特的算法,最多就是可以用用队列,下面是实现步骤。

  1. 解析消息行:这个看代码,用stringstream解析带空格的字符串行是必备技能
  2. 为每个进程设定一个消息队列,将上一步得到的消息依次存入对应的消息队列,这一步可以过滤掉自己发给自己的消息
  3. while一直循环,每次循环过程为一轮执行,遍历每个进程,检查它是否空闲,如果空闲则将它的消息队列中的第一个队列弹出,存入记录本轮要执行的消息数组中,如果进程已经遍历完了且消息数组还是空,那么就退出while循环,如果消息数组不为空则依次执行消息数组中的消息,执行过程见代码。

Warning:注意n的取值范围

#include<iostream>
#include<string>
#include<sstream>
#include<string.h>
#include<stack>
#include<queue>
#include<vector>
#include<list>
#include<set>
#include<map> 
#include<algorithm> 

using namespace std;

typedef long long ll;
typedef pair<int,string> P;

using namespace std;

void split(int j, queue<string>& message,string line)
{
	// 将读入的一行分割为多个命令,并且过滤掉自己发给自己的命令 
	stringstream ss;
	string temp;
	ss.str(line);
	while(1)
	{
		ss >> temp;
		if(ss.fail())
			return ;
		if(stoi(temp.substr(1, temp.size()-1)) != j)     // 不收发自己的 
			message.push(temp);
	}
}


int main()
{
	int T,n;
	string line;
	cin >> T >> n;
	cin.ignore();
	while(T--)
	{
		queue<string> messages[n];
		int waitR[n];       //  等待R操作,waitR[i]=j表示i在等待j执行R操作 
		int waitS[n];       //  等待S操作,waitS[i]=j表示i在等待j执行S操作 
	
		memset(waitR,-1,sizeof(waitR));
		memset(waitS,-1,sizeof(waitS));    // -1表示没有等待,否则表示等待的id 
		
		for(int j = 0;j < n; j++)
		{
			getline(cin,line);
			split(j,messages[j],line);
		}
		
		while(1)
		{
			// 存放本轮运行的消息 
			vector<P> curr;
			for(int j = 0;j < n; j++)
			{
				if(!messages[j].empty())         // 第j个进程还没有执行完 
				{
					if(waitR[j] == -1 && waitS[j] == -1)              //没有被卡住
					{
						curr.push_back(make_pair(j, messages[j].front()));
						messages[j].pop();
					} 	
				}
			}
			
			if(curr.size() == 0)               // 没有消息执行了就退出 
				break;
			
			for(int i = 0;i < curr.size(); i++)
			{
				P t = curr[i];
				
				// 如果是收消息
				if(t.second[0] == 'R')
				{
					int rever = t.first;
					int sender = stoi(t.second.substr(1, t.second.size()-1));
					// 如果对方正在等待发送,则此时可以发送成功 
					if(waitS[sender] == rever)
					 	waitS[sender] = -1;
					else    // 等待接收 
						waitR[rever] = sender;
				}
				else if(t.second[0] == 'S')       // 发消息 
				{
					int sender = t.first;
					int rever = stoi(t.second.substr(1, t.second.size()-1));
					
					if(waitR[rever] == sender)
						waitR[rever] = -1;
					else
						waitS[sender] = rever;
				}
			}
		 
		}
		
		int is_lock = 0;
		for(int i = 0;i < n; i++)
		{
			if(!(waitS[i] == -1 && waitR[i] == -1))
			{
				is_lock = 1;
				break;
			}
		}
		
		cout << is_lock << endl; 
		 
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值