CSP 201903-4 消息传递接口(模拟题) 满分

       耗时就900ms算很慢了,有的帖子用int整型存我觉得很好,但是不常用的人会不熟悉用法,所以我还是直接采用的节点+队列模拟,简单粗暴。

基本思路:

      其实只要某一次跳转成环了且无匹配,就成了死锁,所以就像消消乐一样,消到最后不能消了就有答案了。

实现:

       每个进程命令用一个队列存储,通过send和receive关系每次从第一个不为空的进程处开始跳转,当某次跳转时前后匹配,则前后队列命令出队列,再重新从第一个不为空的进程处开始跳转循环找下去,直到某一次跳转成环且无匹配项(即死锁)或者所有队列为空(匹配成功),退出循环。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>

using namespace std;
const int MAX_N = 10000;

struct Node {
	int sr, flag;
};

int T, n, tmp;
string op;
queue<Node> num[MAX_N];

void make_queue() {
	
	for(int i = 0; i < n; i++) {
		op = "";
        getline(cin, op);
		//将命令入队
		for(int j = 0; j < op.size(); j++) {
			if(op[j] == ' ') continue;
			else if(op[j] == 'R' || op[j] == 'S') {
				tmp = (op[j++] == 'S' ? 1 : -1);
				Node node;
				node.flag = tmp;
				tmp = 0;
				while(j < op.size() && op[j] != ' ') {
					tmp = tmp * 10 + op[j++] - '0';
				}
				node.sr = tmp;
				num[i].push(node);
			}
		}
	}
}

//配对条件为num[p].front().flag != num[q].front().flag 
// && num[q].front().sr == p; 
void is_valid() {
    //用于记录是否成环
	int v[MAX_N] = {0}, is_change = 1, p ,q;
	while(is_change) {
		//reset
		memset(v, 0, sizeof(v));
		p = 0;
		is_change = 0;
		while(p < n && num[p].empty()) p++;
		if(p == n) break;
		q = num[p].front().sr;
		v[p] = 1;
		
		while(!is_change && !v[q] && !num[q].empty()) {
			v[q] = 1;
			
			//match
			if(num[q].front().sr == p && num[p].front().flag != num[q].front().flag) {
				is_change = 1;
				num[p].pop();
				num[q].pop();
				continue;
			}
			p = q;
			q = num[p].front().sr;
		}
	}
    //输出答案顺便清空队列	
	int ans = 0;
	for(int i = 0; i < n; i++) {
		if(!num[i].empty()) {
			ans = 1;
			//清空队列
            queue<Node> empty;
			swap(empty, num[i]);
		}
	}
	cout << ans << endl;
	return ;
}

int main () {
    //带\n可以不影响getline的输入
	scanf("%d%d\n", &T, &n);
	while(T--) {
		make_queue();
		is_valid();
	}
	return 0;
}

 

注意:

可以用getline读取一行,但是在大量数据的情况下会超时,所以用scanf()比较好,本题用scanf可以快100多ms:

char op[10000];
scanf("%[^\n]s", op);
getchar();

后面的getchar()是清除缓冲区的换行符。

但不管哪一种,都要注意在读入一行之前清除缓冲区遗留的换行符。有两种办法:

1、上一个scanf后面带一个\n,就不用清除。

2、上一个scanf后用getchar()

 

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风の梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值