题目来源
链接: DHCP服务器.
解题过程
暴力解法 100分
- 通读了一遍题目后,可以看出来,我们主要是实现 对收到的报文进行格式检查、返回正确格式下的DIS、REQ报文内容对应的报文。格式检查可融入到对DIS、REQ报文的回复中。
- 对 DIS 报文
if (messType == "DIS" && recvHost == "*") {
long long int ip = choseIP(sendHost);
if (ip == 0) {
continue;
}
ips[ip].state = 1;
ips[ip].host = sendHost;
long long int eT = setExpireTime(ti, expiTime);
ips[ip].expiTime = eT;
cout<<H<<" "<<sendHost<<" OFR "<<ip<<" "<<eT<<endl;
}
- 对 REQ 报文
else if (messType == "REQ" && recvHost != "*"){
if (recvHost == H) {
bool flag = false;
if (ipAddr > 0 && ipAddr <= n && ips[ipAddr].state != 0 && ips[ipAddr].host == sendHost) {
flag = true;
}
if ( !flag) {
cout<<H<<" "<<sendHost<<" NAK "<<ipAddr<<" "<<0<<endl;
continue;
}
ips[ipAddr].state = 2;
long long int eT = setExpireTime(ti, expiTime);
ips[ipAddr].expiTime = eT;
cout<<H<<" "<<sendHost<<" ACK "<<ipAddr<<" "<<eT<<endl;
}
else {
cleanUseless(sendHost);
}
}
- 完整代码
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct IP {
string host;
int state;
long long int expiTime;
};
const long long int ipNum = 10001;
IP ips[ipNum];
long long int N, Tdef, Tmax, Tmin;
string H;
long long int n;
void initIPstate() {
for (long long int i = 1; i <= N; ++i) {
ips[i].state = 0;
ips[i].host = "";
ips[i].expiTime = 0;
}
}
long long int choseIP(string &sendHost) {
long long int ip = 0;
for (long long int i = 1; i <= N; ++i) {
if ((ips[i].state == 1 || ips[i].state == 2 || ips[i].state == 3) && ips[i].host == sendHost) {
ip = i;
break;
}
}
if (ip != 0) return ip;
for (long long int i = 1; i <= N; ++i) {
if (ips[i].state == 0) {
ip = i;
break;
}
}
if (ip != 0) return ip;
for (long long int i = 1; i <= N; ++i) {
if (ips[i].state == 3) {
ip = i;
break;
}
}
if (ip != 0) return ip;
return ip;
}
long long int setExpireTime(long long int &t, long long int &expiTime) {
long long int eT;
if (expiTime == 0) {
eT = t + Tdef;
}
else if ((expiTime - t) >= Tmin && (expiTime - t) <= Tmax) {
eT = expiTime;
}
else if ((expiTime - t) < Tmin) {
eT = t + Tmin;
}
else if ((expiTime - t) > Tmax) {
eT = t + Tmax;
}
return eT;
}
void cleanIpAddress(long long int &ti, string &sendHost) {
for (long long int i = 1; i <= N; ++i) {
if (ips[i].state == 1 && ips[i].expiTime <= ti) {
ips[i].state = 0;
ips[i].host = "";
ips[i].expiTime = 0;
}
else if (ips[i].state == 2 && ips[i].expiTime <= ti) {
ips[i].state = 3;
ips[i].expiTime = 0;
}
}
}
void cleanUseless(string &sendhost) {
for (long long int i = 1; i <= n; ++i) {
if (ips[i].host == sendhost && ips[i].state == 1) {
ips[i].state = 0;
ips[i].expiTime = 0;
ips[i].host = "";
}
}
}
int main() {
cin>>N>>Tdef>>Tmax>>Tmin>>H;
cin>>n;
initIPstate();
for (long long int i = 0; i < n; ++i) {
long long int ti, ipAddr, expiTime;
string sendHost, recvHost, messType;
cin>>ti>>sendHost>>recvHost>>messType>>ipAddr>>expiTime;
cleanIpAddress(ti, sendHost);
if (messType == "DIS" && recvHost == "*") {
long long int ip = choseIP(sendHost);
if (ip == 0) {
continue;
}
ips[ip].state = 1;
ips[ip].host = sendHost;
long long int eT = setExpireTime(ti, expiTime);
ips[ip].expiTime = eT;
cout<<H<<" "<<sendHost<<" OFR "<<ip<<" "<<eT<<endl;
}
else if (messType == "REQ" && recvHost != "*"){
if (recvHost == H) {
bool flag = false;
if (ipAddr > 0 && ipAddr <= n && ips[ipAddr].state != 0 && ips[ipAddr].host == sendHost) {
flag = true;
}
if ( !flag) {
cout<<H<<" "<<sendHost<<" NAK "<<ipAddr<<" "<<0<<endl;
continue;
}
ips[ipAddr].state = 2;
long long int eT = setExpireTime(ti, expiTime);
ips[ipAddr].expiTime = eT;
cout<<H<<" "<<sendHost<<" ACK "<<ipAddr<<" "<<eT<<endl;
}
else {
cleanUseless(sendHost);
}
}
}
return 0;
}
非暴力解法 (只有想法)
- 关键思路: 将发送者的名称 (sendHost) 与 ip(ips[i]) 连接 。 通过一个 map<string, int> name2ip ({sendHost, i})实现。
- 代码 (略)
|