参考:
https://www.luogu.com.cn/problem/P7911
总结
本系列为CSP-J/S算法竞赛真题讲解,会按照年份分析每年的真题,并给出对应的答案。本文为2021年真题。 https://www.luogu.com.cn/problem/list?tag=343&page=1
[CSP-J 2021] 网络连接
题目描述
TCP/IP 协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。
在本问题中,计算机分为两大类:服务机(Server
)和客户机(Client
)。服务机负责建立连接,客户机负责加入连接。
需要进行网络连接的计算机共有
台,编号为
,这些机器将按编号递增的顺序,依次发起一条建立连接或加入连接的操作。
每台机器在尝试建立或加入连接时需要提供一个地址串。服务机提供的地址串表示它尝试建立连接的地址,客户机提供的地址串表示它尝试加入连接的地址。
一个符合规范的地址串应当具有以下特征:
- 必须形如
a.b.c.d:e
的格式,其中
均为非负整数;
,
;
均不能含有多余的前导
。
相应地,不符合规范的地址串可能具有以下特征:
- 不是形如
a.b.c.d:e
格式的字符串,例如含有多于
个字符 .
或多于
个字符 :
等情况;
- 整数
中某一个或多个超出上述范围;
- 整数
中某一个或多个含有多余的前导
。
例如,地址串 192.168.0.255:80
是符合规范的,但 192.168.0.999:80
、192.168.00.1:10
、192.168.0.1:088
、192:168:0:1.233
均是不符合规范的。
如果服务机或客户机在发起操作时提供的地址串不符合规范,这条操作将被直接忽略。
在本问题中,我们假定凡是符合上述规范的地址串均可参与正常的连接,你无需考虑每个地址串的实际意义。
由于网络阻塞等原因,不允许两台服务机使用相同的地址串,如果此类现象发生,后一台尝试建立连接的服务机将会无法成功建立连接;除此之外,凡是提供符合规范的地址串的服务机均可成功建立连接。
如果某台提供符合规范的地址的客户机在尝试加入连接时,与先前某台已经成功建立连接的服务机提供的地址串相同,这台客户机就可以成功加入连接,并称其连接到这台服务机;如果找不到这样的服务机,则认为这台客户机无法成功加入连接。
请注意,尽管不允许两台不同的服务机使用相同的地址串,但多台客户机使用同样的地址串,以及同一台服务机同时被多台客户机连接的情况是被允许的。
你的任务很简单:在给出每台计算机的类型以及地址串之后,判断这台计算机的连接情况。
输入格式
第一行,一个正整数
。
接下来
行,每行两个字符串
,按照编号从小到大给出每台计算机的类型及地址串。
其中
保证为字符串 Server
或 Client
之一,
为一个长度不超过
的,仅由数字、字符 .
和字符 :
组成的非空字符串。
每行的两个字符串之间用恰好一个空格分隔开,每行的末尾没有多余的空格。
输出格式
输出共
行,每行一个正整数或字符串表示第
台计算机的连接状态。其中:
如果第
台计算机为服务机,则:
- 如果其提供符合规范的地址串且成功建立连接,输出字符串
OK
。 - 如果其提供符合规范的地址串,但由于先前有相同地址串的服务机而无法成功建立连接,输出字符串
FAIL
。 - 如果其提供的地址串不是符合规范的地址串,输出字符串
ERR
。
如果第
台计算机为客户机,则:
- 如果其提供符合规范的地址串且成功加入连接,输出一个正整数表示这台客户机连接到的服务机的编号。
- 如果其提供符合规范的地址串,但无法成功加入连接时,输出字符串
FAIL
。 - 如果其提供的地址串不是符合规范的地址串,输出字符串
ERR
。
样例 #1
样例输入 #1
代码语言:javascript复制5
Server 192.168.1.1:8080
Server 192.168.1.1:8080
Client 192.168.1.1:8080
Client 192.168.1.1:80
Client 192.168.1.1:99999
样例输出 #1
代码语言:javascript复制OK
FAIL
1
FAIL
ERR
样例 #2
样例输入 #2
代码语言:javascript复制10
Server 192.168.1.1:80
Client 192.168.1.1:80
Client 192.168.1.1:8080
Server 192.168.1.1:80
Server 192.168.1.1:8080
Server 192.168.1.999:0
Client 192.168.1.1.8080
Client 192.168.1.1:8080
Client 192.168.1.1:80
Client 192.168.1.999:0
样例输出 #2
代码语言:javascript复制OK
1
FAIL
FAIL
OK
ERR
ERR
5
1
ERR
样例 #3
样例输入 #3
代码语言:javascript复制见附件中的 network/network3.in。
样例输出 #3
代码语言:javascript复制见附件中的 network/network3.ans。
样例 #4
样例输入 #4
代码语言:javascript复制见附件中的 network/network4.in。
样例输出 #4
代码语言:javascript复制见附件中的 network/network4.ans。
提示
【样例解释 #1】
计算机
为服务机,提供符合规范的地址串 192.168.1.1:8080
,成功建立连接;
计算机
为服务机,提供与计算机
相同的地址串,未能成功建立连接;
计算机
为客户机,提供符合规范的地址串 192.168.1.1:8080
,成功加入连接,并连接到服务机
;
计算机
为客户机,提供符合规范的地址串 192.168.1.1:80
,找不到服务机与其连接;
计算机
为客户机,提供的地址串 192.168.1.1:99999
不符合规范。
【数据范围】
测试点编号 | n ≤ n le n≤ | 特殊性质 |
---|---|---|
1 1 1 | 10 10 10 | 性质 1 2 3 |
2 ∼ 3 2 sim 3 2∼3 | 100 100 100 | 性质 1 2 3 |
4 ∼ 5 4 sim 5 4∼5 | 1000 1000 1000 | 性质 1 2 3 |
6 ∼ 8 6 sim 8 6∼8 | 1000 1000 1000 | 性质 1 2 |
9 ∼ 11 9 sim 11 9∼11 | 1000 1000 1000 | 性质 1 |
12 ∼ 13 12 sim 13 12∼13 | 1000 1000 1000 | 性质 2 |
14 ∼ 15 14 sim 15 14∼15 | 1000 1000 1000 | 性质 4 |
16 ∼ 17 16 sim 17 16∼17 | 1000 1000 1000 | 性质 5 |
18 ∼ 20 18 sim 20 18∼20 | 1000 1000 1000 | 无特殊性质 |
特殊性质
性质 1 2 3
性质 1 2 3
性质 1 2 3
性质 1 2
性质 1
性质 2
性质 4
性质 5
无特殊性质
“性质 1”为:保证所有的地址串均符合规范;
“性质 2”为:保证对于任意两台不同的计算机,如果它们同为服务机或者同为客户机,则它们提供的地址串一定不同;
“性质 3”为:保证任意一台服务机的编号都小于所有的客户机;
“性质 4”为:保证所有的地址串均形如 a.b.c.d:e
的格式,其中
均为不超过
且不含有多余前导
的非负整数;
“性质 5”为:保证所有的地址串均形如 a.b.c.d:e
的格式,其中
均为只含有数字的非空字符串。
对于
的数据,保证
。
【提供 hack 数据感谢】
- xyf007。
答案1
代码语言:javascript复制#include <bits/stdc .h>
//#include<cstdio>//必须包含cstdio头文件
//#include<iostream>
using namespace std;
int n;
bool check(string ip){
return true;
}
map<string,int> server;
int main(){
//freopen("candy.in","r",stdin);
//freopen("candy.out","w",stdout);
cin>>n;
string s,t;
for(int i=1;i<=n;i ){
cin>>s>>t;
if(!check(t)){ //检查ip地址是否合法
cout<<"ERR"<<endl;
continue;
}
if(s =="Server"){
if(server[t]==0){
server[t]=i;
cout <<"OK"<<endl;
}else{
cout<<"FAIL"<<endl;
}
}else{
if(server[t]>0){
cout<<server[t]<<endl;
}else{
cout<<"FAIL"<<endl;
}
}
}
// system("pause");
//fclose(stdin);
//fclose(stdout);
return 0;
}
代码语言:javascript复制#include <bits/stdc .h>
//#include<cstdio>//必须包含cstdio头文件
//#include<iostream>
using namespace std;
struct node{
int id;
string sorc;
string ip;
}a[1010];
bool check(string ip){
return true;
}
int n;
int main(){
//freopen("candy.in","r",stdin);
//freopen("candy.out","w",stdout);
// 接收一个n n为ip的数量
cin>>n;
// 循环
for(int i=1;i<=n;i ){
// 接收 op(Server or Client) ad(adress)
string op,ad;
cin>>op>>ad;
// 判断ip 错误输出ERR
if(!check(ad)){
cout<<"ERR"<<endl;
}
// 判断数组为空 server直接进入OK,Client直接错FAIL
if(i==1){
if(op=="Server"){
a[i].id=i;
a[i].sorc="Server";
a[i].ip=ad;
cout<<"OK"<<endl;
continue;
}else{
cout<<"FAIL"<<endl;
continue;
}
}
//int l = sizeof(a)/sizeof(a[0]);
for(int j=1;j<=n;j ){
if(op=="Server"){
if(a[j].sorc=="Server"){
if(ad==a[j].ip){
cout<<"FAIL"<<endl;
break;
}
}else if(j==n){
a[i].id=i;
a[i].sorc="Server";
a[i].ip=ad;
cout<<"OK"<<endl;
}
}else{
if(a[j].sorc=="Server"){
if(ad==a[j].ip){
cout<<a[j].id<<endl;
break;
}
}else if(j==n){
cout<<"FAIL"<<endl;
}
}
}
}
//system("pause");
//fclose(stdin);
//fclose(stdout);
return 0;
}
答案2
代码语言:javascript复制#include <bits/stdc .h>
//#include<cstdio>//必须包含cstdio头文件
//#include<iostream>
using namespace std;
int n;
bool check(string ip){
int t[6] = {0,-1,-1,-1,-1,-1};
int cnt=sscanf(ip.c_str(),"%d.%d.%d.%d:%d",
&t[1],&t[2],&t[3],&t[4],&t[5]);
if(cnt!=5) return false;
for(int i=1;i<=4;i ){
if(t[i]<0||t[i]>255) return false;
}
if(t[5]<0 || t[5]>65535) return false;
char now[30];
sprintf(now,"%d.%d.%d.%d:%d",t[1],t[2],t[3],t[4],t[5]);
if(string(now) !=ip) return false;
return true;
}
map<string,int> server;
int main(){
//freopen("candy.in","r",stdin);
//freopen("candy.out","w",stdout);
cin>>n;
string s,t;
for(int i=1;i<=n;i ){
cin>>s>>t;
if(!check(t)){ //检查ip地址是否合法
cout<<"ERR"<<endl;
continue;
}
if(s =="Server"){
if(server[t]==0){
server[t]=i;
cout <<"OK"<<endl;
}else{
cout<<"FAIL"<<endl;
}
}else{
if(server[t]>0){
cout<<server[t]<<endl;
}else{
cout<<"FAIL"<<endl;
}
}
}
// system("pause");
//fclose(stdin);
//fclose(stdout);
return 0;
}
现场真题注意事项
https://cspoj.com/contest.php?cid=1002 Fus5yz4x3EcSJH1Z
注意事项
- 文件名(程序名和输入输出文件名)必须使用英文小写。(提交必须使用freopen()进行提交)
- C/C 中函数 main() 的返回值类型必须是 int,程序正常结束时的返回值必须是0。
- 提交的程序代码文件的放置位置请参考各省的具体要求。
- 因违反以上三点而出现的错误或问题,申述时一律不予受理。
- 若无特殊说明,结果的比较方式为全文比较(过滤行末空格及文末回车)。
- 程序可使用的栈空间内存限制与题目的内存限制一致。
- 全国统一评测时采用的机器配置为:Inter® Core™ i7-8700K CPU @3.70GHz,内存 32GB。上述时限以此配置为准。
- 只提供 Linux 格式附加样例文件。
- 评测在当前最新公布的 NOI Linux 下进行,各语言的编译器版本以此为准
/* 假设输入样例数据存在文件test.in中,输出样例数据存在文件test.out中, 则在CSP、NOI等比赛的代码中,需添加freopen、fclose语句, 内容详见模板代码如下。 */
代码语言:javascript复制#include <bits/stdc .h>
#include<cstdio>//必须包含cstdio头文件
#include<iostream>
using namespace std;
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cout<<"Hello NOI"<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
下面为函数的简介,详细可参见 http://www.cplusplus.com/reference/clibrary/cstdio/freopen.html 函数名:freopen 声明:FILE *freopen( const char *path, const char *mode, FILE *stream ); 所在文件: stdio.h 参数说明: path: 文件名,用于存储输入输出的自定义文件名。 mode: 文件打开的模式。和fopen中的模式(如r-只读, w-写)相同。 stream: 一个文件,通常使用标准流文件。 返回值:成功,则返回一个path所指定文件的指针;失败,返回NULL。(一般可以不使用它的返回值) 功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。通过调用freopen,就可以修改标准流文件的默认值,实现重定向。
代码语言:javascript复制#include<iostream>
#include<cstdio>
using namespace std;
int main(){
freopen("7532.in", "r", stdin);
freopen("7532.out", "w", stdout);
//原来的代码保持不变
double a, b, r;
int k;
cin >> a >> b;
k = int(a/b);
r = a - b * k;
printf("%g", r);
//-------------
fclose(stdin);
fclose(stdout);
return 0;
}