前言
只对 SubTask 2 的选手看过来!!!
很好的一道模拟题。
坑点分析
题目里说的很明白了:只要有 \(\ge 1\) 个带有注释的,就是一定是祖宗人,哪怕在后面或者前面出现过符合乐子人的判断。
一组 hack 能简单明了的看出坑点:
1
2 1
IBLIOI
IOIAKME
//freopen();
//freopen();
IOIAKME
显然答案都是祖宗人。
还需要注意关于换行的问题,如果使用 scanf()
和 getchar()
就要麻烦的多,但是使用 cin
就可以避免这个问题。
弄明白这两个坑点,就可以 AC 了。
思路
考虑对每道题生成合法的 .in
与 .out
的 freopen()
,与输入的进行比较,如果完全一致,就是普通人,如果前面有 //freopen
且后面有 );
,就一定是祖宗人,其余情况就是乐子人。
思路是很清晰的,主要是细节问题,在代码里会讲解。
如何生成符合标准的 freopen()
呢?看到只有题目名字不一样,我们就可以用 string
拼接出一个合法的语句。
但是 .in
和 .out
以及 stdin
和 stdout
也存在差异,只需要判断行数是否是偶数就可以了。
这一部分的代码:
for(i=1;i<=2*m;i++)
{
string k = (i%2==1)?".in\",":".out\","; //这是关于后缀名的处理。
string k1 = (i%2==1)?"\"r\",stdin);":"\"w\",stdout);";//这是关于是读入还是输出的处理。
tque[i] = "freopen(\""+que[(i+1)/2]+k+k1;//这是存储合法的语句的数组。
}
关于双引号的细节很多,读者一定要看明白。
现在就开始特判是哪种人了,再次重申:只要有一个符合祖宗人的标准,哪怕同时符合了乐子人的标准,答案还是祖宗人。
对于这一个判断,需要开一个变量 zzr
(是否是祖宗人),只要满足祖宗人的标准,就设为 \(1\),以后如果出现了乐子人,就不管他了。
关于这一部分的代码:
getchar();//把可恶的换行吃掉。
string s;//每一行输入的东西。
int f = 0;//0:RP++,1:Wrong,2:Good。
int zzr;//祖宗人标志。
for(i=1;i<=n;i++)//遍历选手。
{
f = 0;
zzr = 0;//初始为 0。
for(j=1;j<=2*m;j++)//遍历输入。
{
int l;
cin>>s;
l = s.size();
if(zzr)//只要出现了祖宗人,答案一定是祖宗人,跳过就可以了。
continue;
if(s[0]=='/'&&s[1]=='/'&&s[2]=='f'&&s[l-1]==';'&&s[l-2]==')')//判断是否是祖宗人。
{
f = 1;
zzr = 1;
continue;
}
else if(s==tque[j])//普通人。
;
else//不是普通人且不是祖宗人,就是乐子人。
{
f = 2;
continue;
}
}
if(f==0)//判断输出。
puts("PION2202 RP++.");
else if(f==1)
puts("Wrong file operation takes you to your ancestors along with your 3 years\' efforts on OI.");
else
puts("Good luck and have fun.");
}
对于完整程序,把两部分拼起来,并加上输入定义等部分就可以了。
标签:乐子,freopen,题解,zzr,else,&&,祖宗 From: https://www.cnblogs.com/OoXiaoQioO/p/17066062.html