csp21-04-3DHCP服务器-70分蒙蔽版

这道题我处于对第三题的尊重,简单的考虑了时间复杂度的影响,因此对不同状态的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;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值