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

本文介绍了一种基于队列和节点模拟的死锁检测算法,通过消消乐式的匹配过程来判断多进程间的命令是否会导致死锁。使用C++实现,详细解释了算法流程和关键代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       耗时就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()

 

引用: 这是2020年CSP-J入门单项选择题解析,解析明白,一看就懂。整理不易,文章出错评论区说,看见必改。请一键三连,给个五星好评。小编那么拼,给个赞再撤┗|`O′|┛ 嗷~~。 引用: 子任务中显示测试点2正确个数为0,因此,可以用如下方法,骗到10分。以下是一个C++的代码示例: #include <iostream> using namespace std; int main() { int n; cin >> n; for (int i = 0; i < n; i++) { cout << "No" << endl; } return 0; } 以上代码会输出n个"No",可以通过测试点2并获得10分。 引用: 这是一个使用数组和栈实现的C++代码示例: #include <iostream> #include <stack> using namespace std; int main() { char a[100]; int n; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } for (int i = 0; i < n; i++) { int num; //运算数 char oper; //运算符 int sum = 0; for (int j = 0; j < 7; j++) { if (j % 2 == 0) num[j / 2] = a[i][j] - 48; //0的ASSIC码为48 else oper[j / 2] = a[i][j]; } stack<int> snum; stack<char> soper; snum.push(num); for (int i = 0; i < 3; i++) { if (oper[i] == 'x' ||oper[i] == '/') { int temp = snum.top(); snum.pop(); if (oper[i] == 'x') snum.push(temp * num[i + 1]); else snum.push(temp / num[i + 1]); } else if (oper[i] == '-') { snum.push(-num[i + 1]); soper.push(oper[i]); } else { snum.push(num[i + 1]); soper.push(oper[i]); } } sum = snum.top(); snum.pop(); for (int i = 0; i < soper.size(); i++) { sum += snum.top(); snum.pop(); } if (sum == 24) cout << "Yes" << endl; else cout << "No" << endl; } } 以上代码实现了一个解析给定算术表达式是否等于24的程序。 问题:请告诉我,csp201903-2是什么? csp201903-2是一个CSP(全国计算机科学与技术专业资格考试)的题目编号,表示该题是2019年3月份的第2道题目。具体题目内容需要查阅相关资料来获取。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [2020年CSP-J入门单项选择题解析](https://download.youkuaiyun.com/download/sjy100401/88234366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [CSP 201903-2 二十四点 (C++)](https://blog.youkuaiyun.com/qq_39876147/article/details/117091994)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CSP201903-2二十四点](https://blog.youkuaiyun.com/weixin_43074474/article/details/101128023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风の梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值