csp201903-4

csp201903-4

一、getline()数的总结

getline()函数是一个比较常见的函数,用这个函数完成读入一行数据
在C++中getline()函数的有两种,一种是在头文件中,是食istream类的成员函数,另一种在头文件中,是普通函数

第一种:在中的getline()函数有两种重载形式:

istream&getline(char* s,streamsize n);
istream&getline(char* s,streamsize n,char delim);

作用是:从istream中读取至多n个字符(包含结束标记符)保存在s对应的数组中,即使还没读够n个字符

如果遇到delim或字数达到限制,则读取终止,delim都不会被保存进s对应的数组中

第二种: 在中的getline函数有四种重载形式:

istream& getline (istream& is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream& is, string& str);
istream& getline (istream&& is, string& str);

用法和上第一种类似,但是读取的istream是作为参数is传进函数的。读取的字符串保存在string类型的str中。

函数的变量:

is :表示一个输入流,例如cin。

str :string类型的引用,用来存储输入流中的流信息。

delim :char类型的变量,所设置的截断字符;在不自定义设置的情况下,遇到’\n’,则终止输入。

二、istringstream的用法

istringstream是一个比较有用的c++的输入输出控制类。

C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含这个头文件。
istringstream类用于执行C++风格的串流的输入操作。
ostringstream类用于执行C风格的串流的输出操作。
strstream类同时可以支持C风格的串流的输入输出操作。

istringstream的构造函数原形如下:
istringstream::istringstream(string str);
它的作用是从string对象str中读取字符。

#include
#include //istringstream 必须包含这个头文件
#include
using namespace std;
int main()
{
string str=“i an a boy”;
istringstream is(str);
string s;
while(is>>s)
{
cout<<s<<endl;
}

}
输出是:
i
am
a
boy

三、题目分析

首先我自己想的是先用getline输入,然后开n个队列,将不同进程的消息放进各自的队列中,然后开始循环找S和R对应的消息直到最终所有队列加起来的长度不再变化,但是只得了60分,时间复杂度太高了,超时,代码如下:

#include<iostream>
#include<queue>
#include<string>
using namespace std;
int main() {
	int t, n;
	cin >> t >> n;
	queue<string> a[n];
	string c;
	string d;
	getline(cin, d);
	for (int i = 0; i < t; i++) {
		int len = 0;
		for (int j = 0; j < n; j++) {
			getline(cin, c);
			int m = c.length() / 3 + 1;
			for (int k = 0; k < m; k++) {
				string cc = c.substr(3 * k, 2);
				a[j].push(cc);
			}
		}
		for (int j = 0; j < n; j++) {
			len += a[j].size();
		}
		while (true) {
			for (int j = 0; j < n; j++) {
				if (!a[j].empty()) {
					string g = a[j].front();
					if (g[0] == 'R' && !a[g[1] - '0'].empty()) {
						if (a[g[1] - '0'].front()[0] == 'S' && a[g[1] - '0'].front()[1] - '0' == j) {
							a[g[1] - '0'].pop();
							a[j].pop();
						}
					}
					else if (g[0] == 'S' && !a[g[1] - '0'].empty()) {
						if (a[g[1] - '0'].front()[0] == 'R' && a[g[1] - '0'].front()[1] - '0' == j) {
							a[g[1] - '0'].pop();
							a[j].pop();
						}
					}
				}
			}
			int sum = 0;
			for (int j = 0; j < n; j++) {
				sum += a[j].size();
			}
			if (sum == len) break;
			len = sum;
		}
		if (len == 0) cout << 0 << endl;
		else cout << 1 << endl;
		for (int j = 0; j < n; j++) {
			while (!a[j].empty()) {
				a[j].pop();
			}
		}
	}
	return 0;
}

然后我自己又在网上找到了100分的代码,链接地址,代码中用到了递归来解决

主要是三个函数:
int exe(int no) 执行进程no
int receiveM(int from, int to) 进程from从进程to那里接收消息
int sendM(int from, int to) 进程from向进程to那里发送消息

输入完相应的信息后,在主函数中用一个for来判断各个进程的消息队列是否为空,如果都为空的话就不会发生死锁,否则将会导致死锁,在执行各个进程的时候,对其他进程的消息队列也会递归执行,代码如下:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
#include<queue>
using namespace std;
const int MAXN = 10005;
struct Mes { //消息结构体
	char flag; //R:收,S:发
	int target; //目标进程
};
struct Pro { //进程结构体
	queue<Mes> task; //消息队列
};
Pro pro[MAXN]; //进程数组,pro[i]代表进程i
int wait[MAXN]; //进程等待标志,1为等待,0为就绪
int exe(int no) {//执行进程no
	if (wait[no] == 1) return -1; //如果进程处于等待状态,那么发生死锁
	if (pro[no].task.empty()) return 0; //如果进程的消息队列为空,那么表示该进程成功结束
	Mes cur = pro[no].task.front(); //取第一个消息
	if (cur.flag == 'R') {
		wait[no] = 1;
		if (receiveM(no, cur.target) == -1) return -1;
		//如果该消息成功执行
		pro[no].task.pop();
		wait[no] = 0;
		if (exe(no) == -1) return -1; //递归处理该进程的下一个消息
		return 0;
	}
	else if (cur.flag == 'S') {
		wait[no] = 1;
		if (sendM(no, cur.target) == -1) return -1;
		//如果该消息成功执行
		pro[no].task.pop();
		wait[no] = 0;
		if (exe(no) == -1) return -1; //递归处理该进程的下一个消息
		return 0;
	}
}
int receiveM(int from, int to) {//进程from从进程to那里接收消息
	if (wait[to] == 1) return -1; //判断目标进程的状态
	if (pro[to].task.empty()) return -1; //判断目标进程的消息队列是否为空
	Mes cur = pro[to].task.front(); //获取目标进程的消息队列中的第一个消息,判断能否处理来自from的消息
	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') { //因为是'S',或许可以处理当前消息
		if (cur.target == from) { //确实可以处理当前消息
			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;
	}
	return -1;
}
int sendM(int from, int to) {//进程from向进程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 (cur.target == from) {
			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;
	}
	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];h
				mes.target = tmp[1] - '0';
				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);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值