CSDN竞赛60期题解

总结

参加C站比赛的人越来越少了,大概也是因为题目水平一次次的刷新了质量下限吧。反馈的问题很少去解决,新的问题不断的出现。但凡正经的竞赛选手都不会靠这类竞赛来提高算法水平的,还在坚持的兄弟大概也只是为了书籍吧。经常参加的几个兄弟的题解都开启了付费阅读模式,像这种免费的题解也会越来越少了。

本次比赛选择题丢了10分,加上错误的 T 1 T1 T1,成绩并不理想。虽然读题时就知道有问题,但是放弃了在群里艾特主办方的想法,因为历史经验告诉我们,如果题目有问题,你反馈出题方大概率不会理你的;如果题目答案有问题,也只会将错就错,不会去重新评判的,所以久而久之就没人反馈bug了。奔着学习的目的阅读的可以只阅读下 T 2 T2 T2的题解。

题目列表

1.贝博士的论文审阅统计

题目描述

贝博士经常收到申请他审阅论文的信函,每封信函的信封上面只有两个申请人的编号,且每个申请人只能申请审阅一篇论 文,但可以重复申请。贝博士请艾小姐根据信封上的申请人编号统计下:一共有多少篇论文要审阅,最多申请人的论文有 多少人申请?

输入样例:

6 3

1 2

1 3

4 5

输出样例:

3 3

分析

本题的平均得分是0,题目不难,但是出题人的语文水平以及错误的用例让人想得分都难。建议出题人出题后找个审阅题目的,确保别人能读懂他的表达再将题目上线。题目阅读了几十遍,最后还是没有通过一个用例,下面用英语阅读理解的方式来解释下题目。

贝博士经常收到申请他审阅论文的信函

这句话应该是病句,大概意思是这个人经常收到信,这个信是让他帮忙审阅论文的。

每封信函的信封上面只有两个申请人的编号

每个信封上写了两个人的编号,是不是代表着一封信是用来申请一篇论文的审阅的,然后写着两个人的编号代表这篇论文是两个人共同申请的,题目没有说清楚。

且每个申请人只能申请审阅一篇论 文,但可以重复申请。

一种理解是每个人可以多次写申请信,但是贝博士只会给一个人审阅一篇论文,所以会忽略这个人其它的申请;但是可以重复申请加上用例的意思,另一种理解应该更为合理:每个人可以多次写申请信,但是申请的都是同一篇论文,比如用例的一封信上写着1 2,另一封信上写着1 3,都有1申请说明这两封信是申请同一篇论文的。

贝博士请艾小姐根据信封上的申请人编号统计下:一共有多少篇论文要审阅,最多申请人的论文有 多少人申请?

按照上面的分析,一封信代表申请的同一篇论文,两封信上编号相同代表申请的是同一篇论文(这两个关键信息题目都没有说明,需要推理出来),这样理解是可以求出一共有多少篇论文要审阅的。另一句话再次体现了出题人的语文功底了,最容易理解为“最多人申请的论文有多少人申请”,这样理解还是比较合理的,但是这句话写成这样,八成是另一种解释方式:“写了最多申请信的人申请的论文有多少人申请”,比如说1这个人先和2一起写了封申请信,后面又和3一起写了封申请信,由于3和6也一起申请过,说明1 2 3 6申请的是一篇论文,这样这篇论文就有4个人申请,但是这个输出的人数包不包含1自己呢?

题目想要表达的意思应该是想让我们求个并查集,所有共同写过申请信的人申请的都是一篇论文,最后输出并查集的个数以及并查集的大小。但是用例里1 2 3 6共同申请了一篇论文, 4 5一起申请了篇论文,应该输出2 4才对,用例给出3 3的输出只有两种解释:要么是满是病句和不充分信息的题目想要表达的是另一种意思,要么是出题人想出个并查集的题目,但是写的示例代码逻辑有问题,导致用例结果不对,后台测例答案也不对。没有用例解释,到底是什么情况我们也不得而知了。

比赛时写了并查集的代码,鉴于没有得分,就不贴出来了。

2.括号匹配

题目描述

有四种括号:大括号{}、中括号[]、小括号()和尖括号<>。它们之间不能错套,且需要配对。 错套的意思是:某种括号 的前半部分和后半部分之间,仅套着不同类括号的某一半部分而没有另一半部分。错套的样例如下: <<<>>{> ([hello[]]}){world} 因为在尖括号的前半部分和后半部分之间,仅套着大括号的前半部分而没有后半部分。 配对的意思 是:如果出现了某种括号的前半部分,则必须在之后有同样数量的同类括号的后半部分与之对应;反之如果出现了某种括 号的后半部分,则必须在之前有同样数量的同类括号的前半部分与之对应。正确的配对样例如下: <<<>>> ({[hello[]]}){world} 错误的配对样例如下: ))<<<>>([hello[]]){world} 因为前2小括号只有后半部分而缺失了前半 部分,而尖括号的前半部分有3个,而后半部分只有2个。

分析

又是一道较为复杂的模拟题,复杂的地方在于题目的理解,模拟题一般都是冗长的题目描述考察阅读理解,题目一般会给不足够准确的规则让你去理解,这点无可厚非,因为模拟题一旦条理清晰,每个规则都描述清楚就相当于送分题。

这题用例的解释还算明确,唯一不明确的是错误匹配的输出,说是按照大括号到小括号的顺序,左括号、右括号的顺序输出,那么是应该输出{[ }]的顺序还是{} []的顺序呢?用例来看是后一种,这题第一次提交通过了九成用例,后面改成后一种输出顺序就AC了,编码难度不大。

首先理解下题意:题目给了三种结果:

  • 匹配:这个很好理解,类似于[()]这种正常的使用顺序。
  • 错套:比如[),理论上出现[后应该出现],但是错误的出现了其它右括号。
  • 错误配对:这个可以理解为缺失配对,比如[(有左括号没右括号,或者()]]有右括号没对应左括号。

括号匹配问题一般用栈来模拟,模拟的过程就比较考察编程功底了。遍历输入的括号序列,模拟过程如下:

  • 遍历到的是左括号,直接入栈;

  • 遍历到的是右括号:

    首先看栈是否为空,空就说明缺失了配对,记录第三种情况缺失的符号。

    栈非空就看栈顶的左括号与当前右括号是否匹配,匹配栈顶元素就可以出栈,记录下匹配的括号数。

    栈顶左括号与当前右括号不匹配,说明存在错套,直接输出返回即可。

  • 遍历结束,如果栈非空,说明还存在缺失匹配的左括号,需要记录下。

具体的实现细节可以参考代码,添加了详细的注释。

代码

#include <iostream>
#include <map>
#include <string>
#include <stack>
using namespace std;
/*
错套:右括号出现前套着不同括号的左括号但是没有右括号,和栈顶不匹配
错误配对:出现右括号没有左括号,出现左括号没有右括号
*/
stack<char> l;//存储左括号的栈
map<char,char> m;//key-左括号,value-右括号
map<char,int> cnt;//正常匹配的左括号数及数量
map<char, int> mis;//缺失匹配的多余括号及数量
int main() {
	string s;
	getline(cin, s);
	char left[4] = {'{', '[', '(', '<'};
	char right[4] = {'}', ']', ')', '>'};
	for(int i = 0; i < 4; i++) m[left[i]] = right[i];
	int n = s.size();
	bool flag = false;//是否存在错误匹配
	for(int i = 0; i < n; i++) {
		if (s[i] == '{' || s[i] == '[' || s[i] == '(' || s[i] == '<') {
			l.push(s[i]);
		} else if(s[i] == '}' || s[i] == ']' || s[i] == ')' || s[i] == '>') {
			if (!l.size()) {//error match
				mis[s[i]]++;
				flag = true;
			} else {
				char t = l.top();
				if (m[t] == s[i]) {//match
					cnt[t]++;
					l.pop();
				} else {
					cout<<t<<s[i]<<"!"<<endl;
					return 0;
				}
			}
		}
	}
	while (l.size()) {//栈非空存在缺失匹配
		mis[l.top()]++;
		l.pop();
		flag = true;
	}
	if (flag) {
		for (int i = 0; i < 4; i++) {
			if (mis[right[i]]) cout<<mis[right[i]]<<left[i];
			if (mis[left[i]]) cout<<mis[left[i]]<<right[i];
		}
	} else {
		for(int i = 0; i < 4; i++) {
			if(cnt[left[i]]) cout<<cnt[left[i]]<<left[i]<<right[i];
		}
	}
	cout<<endl;
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值