文章目录
- 参考:
- 总结
- [CSP-J 2021] 网络连接
- 题目描述
- 输入格式
- 输出格式
- 样例 #1
- 样例输入 #1
- 样例输出 #1
- 样例 #2
- 样例输入 #2
- 样例输出 #2
- 样例 #3
- 样例输入 #3
- 样例输出 #3
- 样例 #4
- 样例输入 #4
- 样例输出 #4
- 提示
- 答案1
- 答案2
- 现场真题注意事项
参考:
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
)。服务机负责建立连接,客户机负责加入连接。
需要进行网络连接的计算机共有 n n n 台,编号为 1 ∼ n 1 \sim n 1∼n,这些机器将按编号递增的顺序,依次发起一条建立连接或加入连接的操作。
每台机器在尝试建立或加入连接时需要提供一个地址串。服务机提供的地址串表示它尝试建立连接的地址,客户机提供的地址串表示它尝试加入连接的地址。
一个符合规范的地址串应当具有以下特征:
- 必须形如
a.b.c.d:e
的格式,其中 a , b , c , d , e a, b, c, d, e a,b,c,d,e 均为非负整数; - 0 ≤ a , b , c , d ≤ 255 0 \le a, b, c, d \le 255 0≤a,b,c,d≤255, 0 ≤ e ≤ 65535 0 \le e \le 65535 0≤e≤65535;
- a , b , c , d , e a, b, c, d, e a,b,c,d,e 均不能含有多余的前导 0 0 0。
相应地,不符合规范的地址串可能具有以下特征:
- 不是形如
a.b.c.d:e
格式的字符串,例如含有多于 3 3 3 个字符.
或多于 1 1 1 个字符:
等情况; - 整数 a , b , c , d , e a, b, c, d, e a,b,c,d,e 中某一个或多个超出上述范围;
- 整数 a , b , c , d , e a, b, c, d, e a,b,c,d,e 中某一个或多个含有多余的前导 0 0 0。
例如,地址串 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
均是不符合规范的。
如果服务机或客户机在发起操作时提供的地址串不符合规范,这条操作将被直接忽略。
在本问题中,我们假定凡是符合上述规范的地址串均可参与正常的连接,你无需考虑每个地址串的实际意义。
由于网络阻塞等原因,不允许两台服务机使用相同的地址串,如果此类现象发生,后一台尝试建立连接的服务机将会无法成功建立连接;除此之外,凡是提供符合规范的地址串的服务机均可成功建立连接。
如果某台提供符合规范的地址的客户机在尝试加入连接时,与先前某台已经成功建立连接的服务机提供的地址串相同,这台客户机就可以成功加入连接,并称其连接到这台服务机;如果找不到这样的服务机,则认为这台客户机无法成功加入连接。
请注意,尽管不允许两台不同的服务机使用相同的地址串,但多台客户机使用同样的地址串,以及同一台服务机同时被多台客户机连接的情况是被允许的。
你的任务很简单:在给出每台计算机的类型以及地址串之后,判断这台计算机的连接情况。
输入格式
第一行,一个正整数 n n n。
接下来 n n n 行,每行两个字符串 o p , a d \mathit{op}, \mathit{ad} op,ad,按照编号从小到大给出每台计算机的类型及地址串。
其中
o
p
\mathit{op}
op 保证为字符串 Server
或 Client
之一,
a
d
\mathit{ad}
ad 为一个长度不超过
25
25
25 的,仅由数字、字符 .
和字符 :
组成的非空字符串。
每行的两个字符串之间用恰好一个空格分隔开,每行的末尾没有多余的空格。
输出格式
输出共 n n n 行,每行一个正整数或字符串表示第 i i i 台计算机的连接状态。其中:
如果第 i i i 台计算机为服务机,则:
- 如果其提供符合规范的地址串且成功建立连接,输出字符串
OK
。 - 如果其提供符合规范的地址串,但由于先前有相同地址串的服务机而无法成功建立连接,输出字符串
FAIL
。 - 如果其提供的地址串不是符合规范的地址串,输出字符串
ERR
。
如果第 i i i 台计算机为客户机,则:
- 如果其提供符合规范的地址串且成功加入连接,输出一个正整数表示这台客户机连接到的服务机的编号。
- 如果其提供符合规范的地址串,但无法成功加入连接时,输出字符串
FAIL
。 - 如果其提供的地址串不是符合规范的地址串,输出字符串
ERR
。
样例 #1
样例输入 #1
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
OK
FAIL
1
FAIL
ERR
样例 #2
样例输入 #2
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
OK
1
FAIL
FAIL
OK
ERR
ERR
5
1
ERR
样例 #3
样例输入 #3
见附件中的 network/network3.in。
样例输出 #3
见附件中的 network/network3.ans。
样例 #4
样例输入 #4
见附件中的 network/network4.in。
样例输出 #4
见附件中的 network/network4.ans。
提示
【样例解释 #1】
计算机
1
1
1 为服务机,提供符合规范的地址串 192.168.1.1:8080
,成功建立连接;
计算机 2 2 2 为服务机,提供与计算机 1 1 1 相同的地址串,未能成功建立连接;
计算机
3
3
3 为客户机,提供符合规范的地址串 192.168.1.1:8080
,成功加入连接,并连接到服务机
1
1
1;
计算机
4
4
4 为客户机,提供符合规范的地址串 192.168.1.1:80
,找不到服务机与其连接;
计算机
5
5
5 为客户机,提供的地址串 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”为:保证任意一台服务机的编号都小于所有的客户机;
“性质 4”为:保证所有的地址串均形如 a.b.c.d:e
的格式,其中
a
,
b
,
c
,
d
,
e
a, b, c, d, e
a,b,c,d,e 均为不超过
10
9
{10}^9
109 且不含有多余前导
0
0
0 的非负整数;
“性质 5”为:保证所有的地址串均形如 a.b.c.d:e
的格式,其中
a
,
b
,
c
,
d
,
e
a, b, c, d, e
a,b,c,d,e 均为只含有数字的非空字符串。
对于 100 % 100 \% 100% 的数据,保证 1 ≤ n ≤ 1000 1 \le n \le 1000 1≤n≤1000。
【提供 hack 数据感谢】
- xyf007。
答案1
#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;
}
#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
#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语句,
内容详见模板代码如下。
*/
#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,就可以修改标准流文件的默认值,实现重定向。
#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;
}