2021.12.22~12.25 练习CSP 202104-3 DHCP服务器
100分代码
实现过程一定紧扣题中的要求!!!
个人经验:建议实现CSP第三题时新建一个word文档,将题目复制到word里,每实现一个点,就在标注一下,以示区分,这样比较能够清晰的看到自己漏写的条件,方便补充。
注:实现本题过程中需要注意的点已经代码注释内标出
#include
using namespace std;
const int MAX_NUM=10010;
int N;//地址池大小
int T_def;//默认过期时间
int T_max;//过期时间的上限
int T_min;//过期时间的下限
string H;//本机名称
int n;
struct ip
{
int state;
//未分配、待分配、占用、过期
// 0 1 2 3
string owner;//占用者
int tt;//过期时刻
}IP[MAX_NUM];
int main()
{
std::ios::sync_with_stdio(false);
cin>>N>>T_def>>T_max>>T_min>>H;
cin>>n;
//初始化 IP 地址池
for(int i=1;i<=N;i++)
{
IP[i].state=0;
IP[i].owner="";
IP[i].tt=0;
}
for(int t=1;t<=n;t++)
{
string sent;//发送主机
string get;//接收主机
string type;//报文类型
int iP;//IP 地址
int t_over;//过期时刻
int t_get;
cin>>t_get>>sent>>get>>type>>iP>>t_over;
//IP状态更新
for (int i=1;i<=N;i++)
{
//处于待分配和占用状态的 IP 地址拥有一个大于零的过期时刻
if(IP[i].tt>0 && IP[i].tt<=t_get)
//存在过期时刻且已经过期
//注意:是IP[i].tt<=t_get不是IP[i].tt
{
if(IP[i].state==1)
/*在到达该过期时刻时,若该地址的状态是待分配,
则该地址的状态会自动变为未分配,且占用者清空,过期时刻清零;
*/
{
IP[i].state=0;
IP[i].owner="";
IP[i].tt=0;
}
if(IP[i].state==2)
{
IP[i].state=3;
IP[i].tt=0;
}
}
}
int ip_id=-1;
//三种不处理的情况
if( get != H && get != "*")
//注意:之前错写为if( get != H || get != "*")
{
if(type!="REQ")
continue;
}
if (type!="REQ" && type!="DIS")
continue;//注意:之前错写为if (type!="REQ" || type!="DIS")
if ((get=="*"&& type!="DIS")||( get==H && type=="DIS"))
continue;
if(type=="DIS")
{
for(int j=1;j<=N;j++)
{
if(IP[j].owner==sent)
{
ip_id=j;
}
}
if (ip_id==-1)
{
//若没有,则选取最小的状态为未分配的 IP 地址;
int flag_state_0=0;
for(int j=1;j<=N;j++)
{
if(IP[j].state==0)
{
ip_id=j;
flag_state_0=1;
break;
}
}
int flag_state_3=0;
if (flag_state_0==0)
{
//若没有,则选取最小的状态为过期的 IP 地址;
for(int j=1;j<=N;j++)
{
if(IP[j].state==3)
{
ip_id=j;
flag_state_3=1;
break;
}
}
}
/*本题解中设置了一个变量flag_state_0,寻找最小的状态为未分配的 IP 地址,
当没有未分配的 IP 地址时,flag_state_0仍为0,继续设置flag_state_3,
寻找最小的状态为过期的IP地址,当没有过期的IP地址,flag_state_3仍为0,
当没有未分配的 IP 地址时也没有过期的IP地址时,出现下面的情况,不可写为
if(flag_state_3==0),否则当存在未分配的 IP 地址时,仍有flag_state_3=0,
依然会continue,导致处理结束。
*/
if(flag_state_0==0 && flag_state_3==0)
continue;
}
//将该 IP 地址状态设置为待分配,占用者设置为发送主机
IP[ip_id].state=1;
IP[ip_id].owner=sent;
//注意:过期时间的更新需要关注
if(t_over==0)
{
IP[ip_id].tt=t_get+T_def;
}
else
{
if(t_over-t_get<T_min)
{
IP[ip_id].tt=t_get+T_min;
}
else if(t_over-t_get>=T_min&&t_over-t_get<=T_max)
//不可粗心写为t_over-t_get>T_min&&t_over-t_get
{
IP[ip_id].tt=t_over;
}
else if(t_over-t_get>T_max)
{
IP[ip_id].tt=t_get+T_max;
}
}
cout<<H<<" "<<sent<<" "<<"OFR"<<" "<<ip_id<<" "<<IP[ip_id].tt<<endl;
}
if(type=="REQ")
{
if(get!=H)
{
for(int j=1;j<=N;j++)
{
if(IP[j].owner==sent)
{
if(IP[j].state==1)
{
IP[j].state=0;
IP[j].owner="";
IP[j].tt=0;
}
}
}
continue;
}
//iP>=1 && iP<=N用于检查报文中的 IP 地址是否在地址池内
if(!(iP>=1 && iP<=N && IP[iP].owner==sent))
{
ip_id=iP;
cout<<H<<" "<<sent<<" "<<"NAK"<<" "<<ip_id<<" "<<0<<endl;
continue;
}
ip_id=iP;
IP[iP].state=2;
IP[iP].owner=sent;
if(t_over==0)
{
IP[ip_id].tt=t_get+T_def;
}
else
{
if(t_over-t_get<T_min)
{
IP[ip_id].tt=t_get+T_min;
}
else if(t_over-t_get>=T_min&&t_over-t_get<=T_max)
{
IP[ip_id].tt=t_over;
}
else if(t_over-t_get>T_max)
{
IP[ip_id].tt=t_get+T_max;
}
}
cout<<H<<" "<<sent<<" "<<"ACK"<<" "<<ip_id<<" "<<IP[ip_id].tt<<endl;
}
}
return 0;
}
#include
using namespace std;
#define ll long long
const int MAXN=1e4+10;
struct IIP
{
int id;
string owner;
int state;//未分配0、待分配1、占用2、过期3
int tover;
}node[MAXN];
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int N,tdef,tmax,tmin;
string H;
cin>>N>>tdef>>tmax>>tmin>>H;
int n; cin>>n;
int ti;
string send,rec,type;
int id,tdie;
//首先初始化 IP 地址池,将所有地址设置状态为未分配,占用者为空,并清零过期时刻。
for(int i=1;i<=N;i++)
{
node[i].id=i;
node[i].owner="";
node[i].tover=0;
node[i].state=0;
}
while(n--)
{
cin>>ti;
for(int i=1;i<=N;i++)
{
if(node[i].state==1 && node[i].tover<=ti)
{
node[i].state=0;
node[i].owner="";
node[i].tover=0;
}
else if(node[i].state==2 && node[i].tover<=ti)
{
node[i].state=3;
node[i].tover=0;
}
}
cin>>send>>rec>>type>>id>>tdie;
if(rec!=H && rec!="*")
{
if(type!="REQ") continue;
}
if(type!="DIS" && type!="REQ") continue;
if((rec=="*" && type!="DIS") || (rec==H && type=="DIS")) continue;
if(type=="DIS")
{
int ip=0;
int flag=0;
//检查是否有占用者为发送主机的 IP 地址
for(int i=1;i<=N;i++)
{ //若有,则选取该 IP 地址
if(node[i].owner==send)
{
ip=i; flag=1; break;
}
}
//若没有,则选取最小的状态为未分配的 IP 地址
if(flag==0)
{
int f1=0;
for(int i=1;i<=N;i++)
{ //若有,则选取该 IP 地址
if(node[i].state==0)
{
ip=i; f1=1; break;
}
}
//若没有,则选取最小的状态为过期的 IP 地址;
if(f1==0)
{
int f2=0;
for(int i=1;i<=N;i++)
{ //若有,则选取该 IP 地址
if(node[i].state==3)
{
ip=i; f2=1; break;
}
}
if(f2==0) continue;
}
}
node[ip].state=1; //将该 IP 地址状态设置为待分配
node[ip].owner=send;//占用者设置为发送主机
//若报文中过期时刻为0,则设置过期时刻为
if(tdie==0) node[ip].tover=ti+tdef;
else
{
if(tdie-ti>tmax) node[ip].tover=ti+tmax;
else if(tdie-ti<tmin) node[ip].tover=ti+tmin;
else node[ip].tover=tdie;
}
cout<<H<<" "<<send<<" "<<"OFR"<<" "<<ip<<" "<<node[ip].tover<<endl;
}
else if(type=="REQ")
{
if(rec!=H)
{
for(int i=1;i<=N;i++)
{
if(node[i].owner==send)
{
if(node[i].state==1)
{
node[i].state=0;
node[i].owner="";
node[i].tover=0;
}
}
}
continue;
}
if(!((id>=1 && id<=N) && (node[id].owner==send)))
{
cout<<H<<" "<<send<<" "<<"NAK"<<" "<<id<<" "<<0<<endl;
continue;
}
node[id].state=2;
if(tdie==0) node[id].tover=ti+tdef;
else
{
if(tdie-ti>tmax) node[id].tover=ti+tmax;
else if(tdie-ti<tmin) node[id].tover=ti+tmin;
else node[id].tover=tdie;
}
cout<<H<<" "<<send<<" "<<"ACK"<<" "<<id<<" "<<node[id].tover<<endl;
}
}
return 0;
}