2019北航考研机试题解

 

第一场第一题: 

#include<bits/stdc++.h>
#define MAX 150005
#define MOD 1000000007
typedef long long LL;
//const int INF = 1e9+7;
#define VM 1000010
using namespace std;
#define inf 0.00000001

//2019年第一场的第一题,给定区间[a,b],输出这个区间里最长的连续合数段

int a[1000005];
int count1 = 0;
int maxn = 1, tag = 0;

//判断合数
bool judge(int n)
{
    for (int i = 2; i <= (int)sqrt(n); i++)
        if (n%i == 0)
            if (n != 2)
                return true;
    return false;
}

//把合数存到数组a
void save(int n, int m)
{
    for (int i = n; i <=m; i++)
        if (judge(i))
        {
            a[count1] = i;
            count1++;
        }
}

 void compare(int a[])
{
    int m = 1;
    for (int i = 0; i < count1; i++)
        if (a[i + 1] - a[i] == 1)
            m++;
        else
        {
            if (m > maxn)
            {
                maxn = m;
                tag = i;//连续合数的最后一个

            }
            m = 1;
        }
}

//主函数
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    save(n, m);
    compare(a);
    for (int i = tag - maxn+1; i <= tag; i++)
    {
        printf("%d ", a[i]);
    }
    return 0;

}

第二场第一题:

区间素数等差数列

#include<bits/stdc++.h>
#define MAX 150005
#define MOD 1000000007
typedef long long LL;
//const int INF = 1e9+7;
#define VM 1000010
using namespace std;
#define inf 0.00000001

int sushu(int n){
    for(int i = 2;i*i<=n;i++){
        if(n%i==0){
            return 0;
            break;
        }
    }
    return 1;
}

int main()
{
    int a,b,arr[100000];
    int n;
    //scanf("%d",&n);
    //if(sushu(n)==1)printf("1\n");
    scanf("%d%d",&a,&b);
    int k = 0;
    for(int i = a;i<b+1;i++){
        if(sushu(i)==1){
            arr[k] = i;
            //printf("%d ",arr[k]);
            k++;
        }
    }
    //printf("\n\n");
    int count=1,temp=arr[1]-arr[0];
    int ii;
    for(int j=0;j<k;j++){
        ii=j;
        while(arr[ii]+temp == arr[ii+1]){
            count++;
            ii++;
        }
        if(count>2){
            for(int m=0;m<count;m++){
                printf("%d ",arr[ii-count+m+1]);
            }
            printf("\n");
            count=1;
        }
        temp=arr[j+1]-arr[j];
    }
    return 0;
}

第一场第二题:给出几种网络设备(主机、交换机、路由器等),交换机最多八个接口,组成树形网络拓扑,要求给一台主机的编号,求距离它最近的交换机的编号(或者可能是输出路径),如果有多台最近交换机,则输出先序遍历最前边的那个。

这个题没数据,自己设计了一个。思路就是建八叉树,再相应建一个无向图,先把交换机节点按先序顺序先后存一下,然后给一个出发点,以每个交换机节点为出发点bfs无向图求到出发点的最短路(边权视为1,这里懒得用什么高端最短路算法了),顺便存了下路径(第二场第二题其实也可以bfs,思路差不多)。找一个最小的最短路就行。

#include<bits/stdc++.h>
#define MAX 150005
#define MOD 1000000007
typedef long long LL;
//const int INF = 1e9+7;
#define VM 1000010
using namespace std;
#define inf 10000007
/*
struct node{
    char c;
    int num;
    bool operator < (const node &a)const
    {
        if(num!=a.num)
            return num < a.num;
        return c>a.c;
    }
}nd[1005];
template<typename T> string toString(const T& t){
    ostringstream oss;  //创建一个格式化输出流
    oss<<t;             //把值传递如流中
    return oss.str();
}
struct node{
    int id;
    int zl;//设备的类别
    int fz;//分支数
};*/
int que[1005];
int nd[1005][8];
vector<int> dian;
void qxbl(int root){
    if(root!=-1){
        //cout<<root<<" ";
        if(que[root]==3)
            dian.push_back(root);//交换机按先序遍历顺序存储编号
        qxbl(nd[root][0]);
        qxbl(nd[root][1]);
        qxbl(nd[root][2]);
        qxbl(nd[root][3]);
        qxbl(nd[root][4]);
        qxbl(nd[root][5]);
        qxbl(nd[root][6]);
        qxbl(nd[root][7]);
    }
}
//设备类别:1主机 2路由器 3交换机
vector<int> g[1005];//建无向图
int dis[1005];
int path[1005];//存储路径用,需要输出路径就反响找一下即可
int bfs(int st,int ed){
    queue<int> qu;
    int i;
    for(i=0;i<1005;i++)dis[i]=inf;
    dis[st]=0;
    qu.push(st);
    while(!qu.empty()){
        int v=qu.front();
        qu.pop();
        for(i=0;i<g[v].size();i++){
            if(dis[g[v][i]]==inf){
                dis[g[v][i]]=dis[v]+1;
                path[g[v][i]]=v;
                if(g[v][i]==ed)return dis[g[v][i]];
                qu.push(g[v][i]);
            }
        }
    }
    return inf;
}
int main()
{
    int m,q,i,j,k;
    int a[8];
    int root;
    int idx,id,zl;
    scanf("%d",&m);//
    for(i=0;i<m;i++){
        scanf("%d%d",&idx,&zl);
        //scanf("%d%d",&que[i].id,&que[i].zl);
        //scanf("%d",&que[i].fz);
        que[idx]=zl;
        if(i==0)root=idx;
        for(j=0;j<8;j++){//输入结点的分支和该分支的种类,-1表示空
            scanf("%d",&id);
            if(id!=-1){
            scanf("%d",&zl);
            que[id]=zl;
            g[idx].push_back(id);
            g[id].push_back(idx);
            }
            nd[idx][j]=id;
            for(k=0;k<8;k++)nd[id][k]=-1;//默认输入的子节点都是叶子
        }
    }
    qxbl(root);
    //cout<<endl;
    int len=0,aim,ans,minn=MAX;
    scanf("%d",&aim);//出发点

    for(i=0;i<dian.size();i++){
    //cout<<dian[i]<<" ";
    //cout<<endl;
     len = bfs(dian[i],aim);
     if(len<minn){//严格小于才更新
        minn=len;
        ans=i;
     }
    }
    printf("%d %d\n",dian[ans],minn);
    return 0;
}

5
1 1
2 1 3 1 4 2 -1 -1 -1 -1 -1
2 2
5 1 6 3 7 1 8 1 -1 9 1 10 1 -1
4 2
11 1 12 1 -1 -1 -1 -1 -1 -1
6 3
-1 13 1 -1 14 1 15 1 -1 -1 -1
11 1
16 1 -1 -1 -1 -1 -1 -1 -1


第二场第二题:

题目描述:(看的网上学弟的题目描述,很全)一个关于三叉树的题目,小于100的值代表树叶,大于100的值为分支点,建树的过程是水平方向建树,输入格式:

先输入n,代表有n组数据,接下来n行,输入4个数,第一个数代表根节点,接下来分别代表三个子节点,-1代表子节点不存在,输入的顺序按照层次遍历的次序。接下来,要求寻找叶子节点的最短路径,最短路径是指不经过重复的边。输入方式,首先输入一个值m,代表m行,接下来m行输入m个叶子节点和对应的优先级,要求按优先级输出从上次到达的位置到该节点的最短路径,每条路径的最后一个节点要求输出目标叶子节点,最后要求回到根节点。
--------------------- 
作者:sinat_38425013 
来源:CSDN 
原文:https://blog.csdn.net/sinat_38425013/article/details/88749325 

样例:
10
100 101 108 107
101 1 102 2
108 103 104 105
107 17 109 18
102 3 4 5
103 7 8 9
104 10 106 11
105 15 16 -1
109 19 20 21
106 12 13 14
5
8 1
14 3
16 2
5 0
19 4

answer:

100 101 102 5
102 101 100 108 103 8
103 108 105 16
105 108 104 106 14
106 104 108 100 107 109 19
109 107 100

和18年第二题树形态很类似,17年LCA改改其实也可以A这个,主要是换成三叉再加个合并路径。
不过显然bfs写这个题代码量更少(基本和上边那个题一样的写法),不过复杂度就不好说了。。。反正都是小数据量。。
#include<bits/stdc++.h>
#define MAX 150005
#define MOD 1000000007
typedef long long LL;
//const int INF = 1e9+7;
#define VM 1000010
using namespace std;
#define inf 0.00000001
/*
struct node{
    char c;
    int num;
    bool operator < (const node &a)const
    {
        if(num!=a.num)
            return num < a.num;
        return c>a.c;
    }
}nd[1005];
template<typename T> string toString(const T& t){
    ostringstream oss;  //创建一个格式化输出流
    oss<<t;             //把值传递如流中
    return oss.str();
}*/
struct node{
    int id;
    int pri;
}que[1005];
bool cmp(node a,node b){
    return a.pri<b.pri;
}
int nd[1005][3];
vector<int> path1,path2;
//int len1,len2;
void getpath(int d,int root,vector<int> &path){//求根到目标节点的路径(不包含根)
    if(d==root)return ;//根自己
    if(root>=100){
            //printf("%d\n",root);
        for(int i=0;i<3;i++){
            if(nd[root][i]==d){
                path.push_back(d);//判断是否找到目标节点,若找到直接返回
                return ;
            }
            if(nd[root][i]>=100){
                path.push_back(nd[root][i]);
                getpath(d,nd[root][i],path);
            }
            else continue;
            int len=path.size();
            if(!path.empty()&&!(d==path[path.size()-1]))//防止找到目标节点后仍然有其他节点加入路径
                path.erase(path.begin()+len-1,path.begin()+len);
        }
    }
}
void printshortpath(int root){
    vector<int> anspath;
    int times=0; //记录path1元素的访问次数
    int i,j;
    for(i=0;i<path1.size();i++){
        vector<int>::iterator it;
        it = find(path2.begin(),path2.end(),path1[i]);
        if(it!=path2.end()){ //判断path2里含path1的某个节点,即一个LCA
            for(j=path2.size()-1;j>i;j--) //合并路径
                anspath.push_back(path2[j]);
            for(j=i;j<path1.size();j++)
                anspath.push_back(path1[j]);
            break;
        }
        else{
            times++;
            if(times==path1.size()){//path1和path2没有公共元素,LCA是根节点
                for(i=path2.size()-1;i>=0;i--)//合并路径
                    anspath.push_back(path2[i]);
                anspath.push_back(root);
                for(i=0;i<path1.size();i++){
                    anspath.push_back(path1[i]);
                }
            }
        }
    }
    for(i=1;i<anspath.size();i++)//输出路径
        cout<<anspath[i]<<" ";
    cout<<endl;
}
void qxbl(int root){
    if(root!=-1){
        cout<<root<<" ";
        qxbl(nd[root][0]);
        qxbl(nd[root][1]);
        qxbl(nd[root][2]);
    }
}
int main()
{
    int m,q,i,j;
    int a,b,c,d;
    int root;
    scanf("%d",&m);
    for(i=0;i<m;i++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        if(i==0)root=a;
        nd[a][0]=b;
        nd[a][1]=c;
        nd[a][2]=d;
        if(b<100){
            nd[b][0]=nd[b][1]=nd[b][2]=-1;
        }
        if(c<100){
            nd[c][0]=nd[c][1]=nd[c][2]=-1;
        }
        if(d<100){
            nd[d][0]=nd[d][1]=nd[d][2]=-1;
        }
    }
    //qxbl(root);
    //cout<<endl;
    scanf("%d",&q);
    for(i=0;i<q;i++){
       scanf("%d%d",&que[i].id,&que[i].pri);
    }
    sort(que,que+q,cmp);
    //for(i=0;i<q;i++)cout<<que[i].id<<" ";
    //cout<<endl;
    printf("%d ",root);
    for(i=0;i<q;i++){
        //memset(path1,0,sizeof(path1));
        //memset(path2,0,sizeof(path2));
        path1.clear();
        path2.clear();
        //len1=len2=0;
        if(i==0){
            //getpath(root,root,path1);
            getpath(que[0].id,root,path2);
            for(j=0;j<path2.size()-1;j++)
               cout<<path2[j]<<" ";
            cout<<path2[j];
        }
        else{
            getpath(que[i-1].id,root,path2);
            getpath(que[i].id,root,path1);
        }
        /*for(j=0;j<path1.size();j++)
            cout<<path1[j]<<" ";
        cout<<endl;
         for(j=0;j<path2.size();j++)
            cout<<path2[j]<<" ";
        cout<<endl;*/
        printshortpath(root);
    }
    path2.clear();
    getpath(que[q-1].id,root,path2);
    for(j=path2.size()-2;j>=1;j--)
        cout<<path2[j]<<" ";
    cout<<path2[0]<<" "<<root<<endl;
    return 0;
}

 

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值