社区讨论

【警钟长鸣】Linux与Windows的系统差异

P11227[CSP-J 2024] 扑克牌参与者 14已保存回复 28

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
28 条
当前快照
1 份
快照标识符
@m35mx1hb
此快照首次捕获于
2024/11/06 16:46
去年
此快照最后确认于
2024/11/06 17:21
去年
查看原帖

原因分析

如下,一份手动去重的T1代码:
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+7;

int S[20],d[20],h[20],c[20];
int f(char x){
	if(x=='T') return 10;
	if(x=='J') return 11;
	if(x=='Q') return 12;
	if(x=='K') return 13;
	if(x=='A') return 1;
}
signed main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		string s;
		cin>>s;
		if(s[0]=='S'){
			if(s[1]>='0'&&s[1]<='9'){
				S[s[1]-'0']=1;
			}
			else S[f(s[1])]=1;
		}
		else if(s[0]=='D'){
			if(s[1]>='0'&&s[1]<='9'){
				d[s[1]-'0']=1;
			}
			else d[f(s[1])]=1;
		}
		else if(s[0]=='H'){
			if(s[1]>='0'&&s[1]<='9'){
				h[s[1]-'0']=1;
			}
			else h[f(s[1])]=1;
		}
		else{
			if(s[1]>='0'&&s[1]<='9'){
				c[s[1]-'0']=1;
			}
			else c[f(s[1])]=1;
		}
	}
	int ans=0;
	for(int i=1;i<=13;i++){
		if(!h[i]) ans++;
		if(!c[i]) ans++;
		if(!S[i]) ans++;
		if(!d[i]) ans++;
	}
	cout<<ans;
	return 0;
} 
如果这么些,那么 100pts -> 10pts
代码本质没有问题,但是,注意这个函数:
CPP
int f(char x){
	if(x=='T') return 10;
	if(x=='J') return 11;
	if(x=='Q') return 12;
	if(x=='K') return 13;
	if(x=='A') return 1;
}
我们注意到,这个函数在中途就会 return 掉。
在一般的 Windows 操作系统以及洛谷的 Linux 里,函数的确会正常运行。但是在 NOI Linux 及个别 Linux 操作系统中,由于函数(包括主函数)中途退出,导致破坏了代码从上到下运行的逻辑顺序,可能会出现返回值错误甚至 RE 的情况。
打个比方,正常的代码逻辑如下图所示:
但是,如果函数中途返回,那么代码逻辑就会如下图所示:
可以见到,代码并没有按规矩地向正常结束点走,而是中途结束。再换个形象的类比,跑步马拉松时,其他选手按照跑道跑了全程,而小明按照另一条小道跑到终点。如果没有查出作弊,那么小明的结果将于其它选手相同。但如果裁判发现了作弊行为,那么小明将被取消成绩。

避免方法

为了避免函数中途退出,可以采用以下几种方法:

一、变量替换

CPP
int f(char x){
	int res=0; 
	if(x=='T') res=10;
	if(x=='J') res=11;
	if(x=='Q') res=12;
	if(x=='K') res=13;
	if(x=='A') res=1;
	return res;
}
像这份代码,使用 res 变量存储函数返回值,统一返回。

二、善用 goto 语句

使用 goto ,能在保证代码逻辑的情况下,跳过部分语句。在上文提到的马拉松中,goto 语句就相当于小明只记录部分的跑步过程,其余跑步过程中,小明依靠异于常人的肌肉记忆,边睡边跑(可能有点奇怪)。最后结果相同,也没有“作弊”情况。

使用方法

CPP
'goto'前的语句;
goto end(名称);
中间语句; 
end : 希望 'goto'前的语句跳转至的语句 
此方法大多在主函数中有特判等情况。

三、使用分支语句及contiue

使用分支语句,可以进行简单的分类处理。但当分类过于复杂时,不怎么简便。
continue 适用于循环内跳过部分程序,缺点是有局限性。
综上,注意程序的运行逻辑,防止挂分 挂90分,捕获啦。 祝大家各类赛事 rp++ !

回复

28 条回复,欢迎继续交流。

正在加载回复...