CSP 202104-3 DHCP服务器练习笔记

2021.12.22~12.25 练习CSP 202104-3 DHCP服务器
100分代码
实现过程一定紧扣题中的要求!!!
个人经验:建议实现CSP第三题时新建一个word文档,将题目复制到word里,每实现一个点,就在标注一下,以示区分,这样比较能够清晰的看到自己漏写的条件,方便补充。

注:实现本题过程中需要注意的点已经代码注释内标出

#include <bits/stdc++.h>
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<t_get
            {
                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<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<<" "<<"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 <bits/stdc++.h>
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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值