问题分析:
这道题是一个相对简单的大模拟,只要抓住题中的细节信息就可以很容易的做出。
首先明确题目要求的DHCP报文格式
<发送主机> <接收主机> <报文类型> <IP 地址> <过期时刻>
其次关注题目中所定义的分配策略。我们可以直接看其实现细节即可,其余信息对我们没有帮助。通过阅读题目,显然我们需要维护一个地址池来进行操作,由于数据量并没有很大,所以在操作时直接遍历爆搜即可。
首先定义地址池
struct IPinf
{
ll state;//代表状态
ll T;//代表时限
string user;//代表该IP的占用者
};
操作可以分为下面五种
- 对服务器初始化
在 DHCP 启动时,首先初始化 IP 地址池,将所有地址设置状态为未分配,占用者为空,并清零过期时刻。
void ini()
{
for(int i=1;i<=N;i++)
{
IPs[i].state = 0;
IPs[i].T = 0;
IPs[i].user = "";
}
}
- 对收到的不合规报文不进行处理
if(!(server==H||(server=="*")))
{
if(type != "REQ")
continue;
}
if(!(type=="REQ"||type=="DIS"))
continue;
if(((server == "*"&&type!="DIS") || (server==H&&type=="DIS")))
continue;
- 对IP地址池进行更新
在合法的操作之前进行更新即可,将超出时限的IP根据题目规则进行状态变换。
void update(ll ti)
{
for(int i=1;i<=N;i++)
{
if(IPs[i].T!=0 && IPs[i].T <= ti)
{
if(IPs[i].state == 1)
{
IPs[i].state = 0;
IPs[i].T = 0;
IPs[i].user = "";
}
else if(IPs[i].state == 2)
{
IPs[i].state = 3;
IPs[i].T = 0;
}
}
}
}
- 处理Discover报文
void DIS(ll ti, ll Tdef, ll T, string client)
{
ll IP_to_client=0; //先定义将要分配的IP
int flag = 0;//定义flag,判断是否能够正确分配IP
for(int i=1;i<=N;i++)
{
if(IPs[i].user == client) //题目要求的条件1
{ //如果有使用者为当前user的IP,则直接分配
IP_to_client = i;
flag = 1;
break;
}
}
for(int i=1;i<=N &&flag == 0;i++)//题目要求的条件二
{ //如果存在未被分配的IP,则用最小的分配
if(IPs[i].state==0)
{
IP_to_client = i;
flag = 2;
break;
}
}
for(int i=1;i<=N&&flag==0;i++)//题目要求条件三
{ //如果不存在未被分配的IP,则用最小的超时的IP分配
if(IPs[i].state==3)
{
IP_to_client = i;
flag = 3;
break;
}
}
if(flag == 0)//如果都没能分配,则直接返回不作处理
return;
ll tempt;
if(T==0)//如果没有指定时限,则自动分配
tempt = ti+Tdef;
else//如果指定时限,那么判断是否合规,然后分配
{
tempt = T-ti;
tempt = min(tempt, Tmax);
tempt = max(tempt, Tmin);
tempt = tempt+ti;
}
//存入状态
IPs[IP_to_client].state = 1;
IPs[IP_to_client].user = client;
IPs[IP_to_client].T = tempt;
//按要求输出即可
cout<<H<<" "<<client<<" "<<"OFR"<< " "<<IP_to_client<<" "<<tempt<<endl;
}
- 处理Request报文
void REQ(ll ti, ll T, int IP, string client, string server)
{
if(server!=H)//如果server不是DHCP主机,则清除其待分配的IP。
{
for(int i=1;i<=N;i++)
{
if(IPs[i].state == 1&&IPs[i].user == client)
{
IPs[i].state = 0;
IPs[i].T = 0;
IPs[i].user = "";
}
}
return;
}
if(!(IP>=1&&IP<=N && IPs[IP].user == client))
{ //如果当前IP的user不是自己,则输出NAK
cout<<H<<" "<<client<<" "<<"NAK"<<" "<<IP<<" "<<0<<endl;
}
else//否则按照要求改变IP的状态,并输出结果。
{
IPs[IP].state = 2;
IPs[IP].user = client;
ll tempt;
if(T==0)
tempt = ti+Tdef;
else
{
tempt = T-ti;
tempt = min(tempt, Tmax);
tempt = max(tempt, Tmin);
tempt = tempt+ti;
}
IPs[IP].T = tempt;
cout<<H<<" "<<client<<" "<<"ACK"<<" "<<IP<<" "<<tempt<<endl;
}
}
完整代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct IPinf
{
ll state;
ll T;
string user;
};
ll N,Tdef,Tmax,Tmin;
string H;
IPinf IPs[10005];
void ini()
{
for(int i=1;i<=N;i++)
{
IPs[i].state = 0;
IPs[i].T = 0;
IPs[i].user = "";
}
}
void update(ll ti)
{
for(int i=1;i<=N;i++)
{
if(IPs[i].T!=0 && IPs[i].T <= ti)
{
if(IPs[i].state == 1)
{
IPs[i].state = 0;
IPs[i].T = 0;
IPs[i].user = "";
}
else if(IPs[i].state == 2)
{
IPs[i].state = 3;
IPs[i].T = 0;
}
}
}
}
void DIS(ll ti, ll Tdef, ll T, string client)
{
ll IP_to_client=0;
int flag = 0;
for(int i=1;i<=N;i++)
{
if(IPs[i].user == client)
{
IP_to_client = i;
flag = 1;
break;
}
}
for(int i=1;i<=N &&flag == 0;i++)
{
if(IPs[i].state==0)
{
IP_to_client = i;
flag = 2;
break;
}
}
for(int i=1;i<=N&&flag==0;i++)
{
if(IPs[i].state==3)
{
IP_to_client = i;
flag = 3;
break;
}
}
if(flag == 0)
return;
ll tempt;
if(T==0)
tempt = ti+Tdef;
else
{
tempt = T-ti;
tempt = min(tempt, Tmax);
tempt = max(tempt, Tmin);
tempt = tempt+ti;
}
IPs[IP_to_client].state = 1;
IPs[IP_to_client].user = client;
IPs[IP_to_client].T = tempt;
cout<<H<<" "<<client<<" "<<"OFR"<< " "<<IP_to_client<<" "<<tempt<<endl;
}
void REQ(ll ti, ll T, int IP, string client, string server)
{
if(server!=H)
{
for(int i=1;i<=N;i++)
{
if(IPs[i].state == 1&&IPs[i].user == client)
{
IPs[i].state = 0;
IPs[i].T = 0;
IPs[i].user = "";
}
}
return;
}
if(!(IP>=1&&IP<=N && IPs[IP].user == client))
{
cout<<H<<" "<<client<<" "<<"NAK"<<" "<<IP<<" "<<0<<endl;
}
else
{
IPs[IP].state = 2;
IPs[IP].user = client;
ll tempt;
if(T==0)
tempt = ti+Tdef;
else
{
tempt = T-ti;
tempt = min(tempt, Tmax);
tempt = max(tempt, Tmin);
tempt = tempt+ti;
}
IPs[IP].T = tempt;
cout<<H<<" "<<client<<" "<<"ACK"<<" "<<IP<<" "<<tempt<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>N>>Tdef>>Tmax>>Tmin>>H;
int n;
cin>>n;
ini();
while(n--)
{
ll ti;
string client,server,type;
ll IP, T;
cin>>ti>>client>>server>>type>>IP>>T;
if(!(server==H||(server=="*")))
{
if(type != "REQ")
continue;
}
if(!(type=="REQ"||type=="DIS"))
continue;
if(((server == "*"&&type!="DIS") || (server==H&&type=="DIS")))
continue;
update(ti);
if(type == "DIS")
{
DIS(ti,Tdef,T,client);
}
else if(type == "REQ")
{
REQ(ti,T,IP,client,server);
}
}
return 0;
}