这道题我处于对第三题的尊重,简单的考虑了时间复杂度的影响,因此对不同状态的IP地址设置了一个状态的set集合,为的是在配置IP时能更快找到需要的IP地址,但最终只有70分。后面看其他题主并没有考虑复杂度,直接在每次需要时遍历所有的IP结构来查找对应的,而且没超时。但是就是不懂自己为什么只有70分,感觉没问题啊啊,先记录一下,有缘的大佬可以帮我看看。
---------------
隔了好几天,又来重新看这道题,我还是觉得自己的逻辑没问题,我这道题是考虑怕卡时间,就用了一些stl容器存储信息,为的是能快一点,不用遍历IP地址,但是好像和遍历的时间差不多,而且不能ac,不知道是什么原因,还是没有改出来,考试的时候先多暴力一下吧。
//2104DHCP协议----70分蒙蔽版
#include<bits/stdc++.h>
using namespace std;
int N, Tdef, Tmx, Tmn, n;
string H; // dhcp服务器名
// 定义IP结构
struct IP_ {
int state; // 0-未分配 1-待分配 2-占用 3-过期
string hostId; // 被占用者
int ddl;
IP_() {
state = 0; hostId = ""; ddl = 0;
}
}pp[10005];
set<int> s0; // 未分配----默认升序
set<int> s1; // 待分配
set<int> s4; // 占用
set<int> s3; // 过期
map<string, int> s2; // 记录待分配、过期、占用三个状态下的对应关系
int t;
string shost, rhost, type;
int ipt, tt; // 设置输入报文信息
void handle_dis() {
int ans_ip;
// 寻找IP地址
auto it = s2.find(shost);
if(it!=s2.end()) {
ans_ip = it->second;
s2.erase(pp[ans_ip].hostId);
}
else if(!s0.empty()) {
ans_ip = *s0.begin();
s0.erase(ans_ip);
}
else if(!s3.empty()) {
ans_ip = *s3.begin();
string hh = pp[ans_ip].hostId; // 在过期中将占用对应关系删除
s2.erase(hh);
s3.erase(ans_ip);
}
else {
return; // 没有找到ip,不做处理
}
// 寻找成功,设置相关信息
pp[ans_ip].state = 1; pp[ans_ip].hostId = shost;
int tempt;
if(tt==0) tempt = t+Tdef;
else {
if(tt-t>Tmx) tempt = t+Tmx;
else if(tt-t<Tmn) tempt = t+Tmn;
else tempt = tt;
}
pp[ans_ip].ddl = tempt; // 设置过期时间
s1.insert(ans_ip); // 将ip加入待分配集合
s2.insert({shost, ans_ip});
// 输出offer报文
cout << H << " " << shost << " " << "OFR " << ans_ip << " " << tempt << endl;
}
void handle_req() {
// 检查是否为本机
if(rhost!=H) { // 占用者为发送主机的待分配ip处理
if(s2.find(shost)==s2.end()) return;
// 将待分配的状态设置为未分配,并清除相关设置
auto it = s2.find(shost);
int t_id = it->second;
if(pp[t_id].state==1) {
pp[t_id].state = 0; pp[t_id].hostId = ""; pp[t_id].ddl = 0;
s0.insert(t_id); s1.erase(t_id); s2.erase(shost);
}
}
else { // 为本机
if(ipt<=0 || ipt>N || pp[ipt].hostId!=shost) {
cout << H << " " << shost << " " << "NAK " << ipt << " " << 0 << endl;
return;
}
// ack相关设置和操作
pp[ipt].state = 2;
pp[ipt].hostId = shost;
s4.insert(ipt);
s2.insert({shost, ipt});
s1.erase(ipt); s3.erase(ipt);
int tempt;
if(tt==0) tempt = t+Tdef;
else {
if(tt-t>Tmx) tempt = t+Tmx;
else if(tt-t<Tmn) tempt = t+Tmn;
else tempt = tt;
}
pp[ipt].ddl = tempt; // 设置过期时间
// 输出ACK报文
cout << H << " " << shost << " " << "ACK " << ipt << " " << tempt << endl;
}
}
// 判断是否过期
void judge() {
// 先查看待分配
for(auto it=s1.begin(); it!=s1.end();) {
if(pp[*it].ddl<=t) { // 过期了
s2.erase(pp[*it].hostId);
pp[*it].state = 0; pp[*it].hostId = ""; pp[*it].ddl = 0;
s0.insert(*it);
it = s1.erase(it);
}else it++;
}
// 查看占用关系
for(auto it=s4.begin(); it!=s4.end();) {
if(pp[*it].ddl<=t) {
pp[*it].state = 3; pp[*it].ddl = 0;
s3.insert(*it);
it = s4.erase(it);
} else it++;
}
return;
}
int main() {
cin >> N >> Tdef >> Tmx >> Tmn >> H >> n;
// 设置初始化!!!
// 将s0设置为所有的ip编号
for(int i=1; i<=N; i++) {
s0.insert(i);
}
for(int i=0; i<n; i++) {
cin >> t;
judge();
cin >> shost >> rhost >> type >> ipt >> tt;
// 处理不对的报文格式
if(type!="DIS"&&type!="REQ") continue;
if((rhost=="*"&&type!="DIS")) continue;
if((rhost==H&&type=="DIS")) continue;
if(type=="DIS") { // discover报文
handle_dis();
}
else if(type=="REQ") { // req报文
handle_req();
}
}
return 0;
}