2012年北邮网研院复试上机题目

2012年北邮网研院复试上机题目

2012.网研院.Problem A.打印字符串

链接1: http://10.105.242.83/problem/132 链接2: http://10.105.242.80/problem/p/99

题目描述
老师有一个问题想考考mabo,但是mabo不会,所以想请你来帮帮忙。
问题如下:
给一串字符串,统计其中某个字符的个数。

输入格式
首先输入一个整数T,表示一共有T组数据 0<T<=10。
接下来每行一个字母x(x为’a’-'z’或者‘A’-‘Z’)。
然后下面一行输入一个字符串s(0<s的长度<1000)。

输出格式
统计这个字母在这个字符串中出现的次数

输入样例

2
a
absd
b
bbssb

输出样例

1
3

代码实现

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int T;
    cin >> T;
    int count[10] = {0};
    char c;
    char s[1000];
    int i, j;
    for( i = 0; i < T; i++ )
    {
        cin >> c;
        cin >> s;
        for( j = 0; j < strlen(s); j++ )
            if( s[j] == c )
                count[i]++;
    }
    for( i = 0; i < T; i++ )
        cout << count[i] << endl;
    return 0;
}
2012.网研院.Problem B.二叉树的层数

链接1: http://10.105.242.83/problem/133 链接2: http://10.105.242.80/problem/p/100

题目描述
老师有一个问题想考考mabo,但是mabo不会,所以想请你来帮帮忙。

问题如下:

给一个二叉树

请把这个棵二叉树按层来打印。如果为相同层,需要从左到右打印。一个节点是先添加左节点后添加右节点,即添加顺序与输入顺序一致。

输入格式
首先输入一个整数T,表示一共有T组数据 0<T<=10

再输入两个整数N,M(0<=N,M<=100)

表示下面有N行,这个树有M个节点(1号节点是这棵树的根节点)

每一行两个整数a,b(1<=a,b<=M)

表示节点a的父亲是节点b

输出格式
对于每组

先输出一行 "Qi:"表示第i个问题

然后接下来输出每个问题二叉树每层的节点,在同一层的节点用空格分开,同一层输出在一行(每一行末尾没有空格),不同的层输出在不同行(入下面Sample Ouput所示)

输入样例

2
4 5
2 1
3 1
4 2
5 4
1 2
2 1

输出样例

Q1:
1
2 3
4
5
Q2:
1
2

思路
此题使用二叉树模板,定义节点、构造节点并且初始化、构造树
用递归的方法 求树的深度
树的层次遍历

代码实现

#include <iostream>
#include <queue>
using namespace std;

const int maxsize = 500;
///二叉树模板
typedef struct BiNode
{
    int data;
    int lc;             ///左孩子的数组下标
    int rc;             ///右孩子的数组下标
    int deep;
    bool turnOn;        ///此二叉树节点是否有效
    BiNode()
    {
        initNode();
    }

    void initNode()
    {
        turnOn = false;
        deep = -1;
        lc = rc = -1;
    }
};

BiNode Tree[maxsize]; ///用一维数组来存储一颗二叉树

int cursor;
int t, n, m;

int createNode( int index )     ///在数组下标 x 处创造一个节点
{
    Tree[index].data = index;
    Tree[index].turnOn = true;
    Tree[index].lc = Tree[index].rc = -1;
    return index;
}

void creatTree()
{
    int a,b;            /// a 的 父节点是 b;
    createNode(0);      ///创建根节点
    cin >> n >> m;        /// n 行 m 个 节点
    while( n-- )
    {
        cin >> a >> b;
        a--; b--;
        createNode( a ); ///创建 a 节点
        if( Tree[b].lc == -1 )   /// 无座孩子 先写入左孩子
            Tree[b].lc = a;
        else
            Tree[b].rc = a;
    }
}

void freeNode( int index )
{
    Tree[index].initNode();
}

void freeTree( int index )      ///采用递归的方式释放一棵树( 后序方式 )
{
    if( index == -1 )      /// 递归出口
        return;
    freeTree( Tree[index].lc ); ///递归删除左子树
    freeTree( Tree[index].rc ); ///递归删除右子树
    Tree[index].initNode();     ///删除根节点
}

void calDeep( int root, int nowDeep )       ///先序递归方式求出各节点所在的层次
{
    if( root == -1 )
        return;
    Tree[root].deep = nowDeep;
    calDeep( Tree[root].lc, nowDeep+1 );
    calDeep( Tree[root].rc, nowDeep+1 );
}

void levelOrder( int root )           ///从第 nowDeep 层开始 非递归的层次遍历root 为根节点的二叉树
{
    bool firstCase = true;
    int nowDeep = 1;

    queue<BiNode> q;
    while( !q.empty() )     ///队列初始化
        q.pop();
    q.push( Tree[root] );    ///根节点入队
    while( !q.empty() )
    {
        BiNode &nowNode = q.front();
        q.pop();
        if( nowNode.deep != nowDeep )   ///到了下一层
        {
            cout << endl;
            nowDeep++;
            firstCase = true;
        }
        if( firstCase )
            firstCase = false;
        else
            cout << " ";
        cout << nowNode.data+1;         ///访问节点
        if( nowNode.lc != -1 )
            q.push( Tree[nowNode.lc] );
        if( nowNode.rc != -1 )
            q.push( Tree[nowNode.rc] );
    }
}


int main()
{
    int T;
    cin >> T;
    for( int time = 0; time < T; time++ )
    {
        for( int i = 0; i < maxsize; i++ )
            Tree[i].initNode();
        creatTree();
        calDeep(0, 1);
        cout << "Q" << time+1 << ":" << endl;
        levelOrder(0);
        cout << endl;
    }
    return 0;
}
2012.网研院.Problem C. IP地址

链接1: http://10.105.242.83/problem/134 链接2: http://10.105.242.80/problem/p/101

题目描述
我们都学过计算机网络,了解IPV4地址的点分十进制表示法。
你的任务很简单:判断一个字符串是否是一个合法的点分十进制表示的IPV4地址。
最低的IP地址是0.0.0.0,最高的IP地址是255.255.255.255。
PS :方便起见,认为形似00.00.00.00的IP地址也是合法的。

输入格式
第一行是一个整数T,代表输入还剩下T行
以下的T行,每行都是一个字符串(不含空白字符)。字符串的长度保证不超过15,不小于1.

输出格式
对于每个字符串,输出一行。
如果它是一个合法的IPV4地址,输出Yes。
否则,输出No。

输入样例

3
59.64.130.18
f.a.t.e
1.23.45.678

输出样例

Yes
No
No

思路一
Ip地址 三个点 四串数字
错误思路1:当前字符为数字时,设 num 记录数字
当前字符为 “.” 时, 数点数量,超3停止。同时 如果num 不为 0,设num = 0, 如果num = 0,则前一个字符也是点,停止
这种思路是错的,因为 0.0.0.0 也是合法的。
正确思路:为数字时,如果前一字符是 ‘.’,则数字计数++, 记录当前数字,判断是否超过255
为 ‘.’ 时,判断前一个字符是是否也为 ‘.’ ,同时点计数++。

代码实现

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int T;
    cin >> T;
    string str;
    for(int  i = 0; i < T; i++ )
    {
        int countdot = 0;
        int countnet = 0;
        int net = 0;
        bool flag = true;
        cin >> str;
        for(int j = 0; j < str.size(); j++ )
            if( isdigit(str[j]))
            {
                if( j == 0 || str[j-1] == '.' )
                    countnet++;
                net = net * 10 + str[j] - '0';///cout << " net = " << net << endl;
                if( net > 255 )
                {
                    flag = false;
                    break;
                }
            }
            else if( str[j] == '.' )
            {
                countdot++;
                if( countdot > 3 || str[j-1] == '.' )
                {
                    flag = false;
                    break;
                }
                else
                    net = 0;
            }
            else
            {
                flag = false;
                break;
            }
        if( flag && countnet == 4 )
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}

思路二:
这题着实是坑爹了。所以总结题目的意思是:各种非法输入都可能发生,所有情况都得考虑到。故最佳方法就是用
scanf("%d.%d.%d.%d%c",&x[0],&x[1],&x[2],&x[3],&c);
来进行判断是否输入合法。
然而倘若如此,若最后一个%d处没有输入元素,则程序会一直等待输入流输入一个数字,导致无法进行下去。而且使用此法的话当后续串没有被读入时,还得追加一个字符串读入函数进行后处理,十分的麻烦
解决的方法就是先将本行输入全部装入str串里头,然后使用sscanf进行读取,这样首先免去了末尾对费串的后处理,而且由于sscanf读的是str串,故在最后的%d处若没有元素可读会直接读取失败,而不会等待,因为str串的字符流是确定的,缺少数字元素就是缺少,不会继续等待录入。然后在最后追加一个%c,如果后面有费串则sscanf的返回值会+1。通过判断
scanf("%d.%d.%d.%d%c",&x[0],&x[1],&x[2],&x[3],&c);
符合这样格式的输入的返回值是否严格==4,即可从格式上来界定此次输入是否合法,若合法紧接着只要专心对数字范围进行界定即可。

本题要学到的一个重要技巧就是sscanf()函数的使用,可以方便地从串字符流中读取,模拟scanf从输入流中读取。并且比后者有着不会一直傻等输入的优点。
代码实现

#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x7fffffff
#define MAXSIZE 20
using namespace std;

int main(){
    int t;
    int x[4];
    char str[MAXSIZE];
    char c;
    bool legal;
    int count;
    scanf("%d",&t);
    while (t--){
        //initiate
        legal=true;
        //input
        scanf("%s",str);
        count=sscanf(str,"%d.%d.%d.%d%c",&x[0],&x[1],&x[2],&x[3],&c);
        if (count!=4){//各种输入不合法全囊括在这个判断里
        //即:输入不按照格式,中间夹带非法字符,末尾有非法字符,分隔符之间没有元素 等
            legal=false;
        }
        else{//输入为n.n.n.n格式
            for (int i=0;i<4;i++){
                if (x[i]<0||x[i]>255){
                    legal=false;
                    break;
                }
            }
        }
        //output
        printf("%s\n",legal?"Yes":"No");

    }
    return true;
}
2012.网研院.Problem D.最远距离

链接1: http://10.105.242.83/problem/135 链接2: http://10.105.242.80/problem/p/102

题目描述
正义的伙伴褋祈和葬仪社的机器人Fuyuneru正在被邪恶的GHQ部队追杀。眼看着快要逃不掉了,祈就把重要的东西塞到了机器人体内,让它先跑,自己吸引火力。

假设Fuyuneru带上东西开始逃跑时所处的点为原点,朝向为正北。操纵FuyuNeru的指令有如下四种:
right X: X是1-359之间的整数,Fuyuneru的前进方向顺时针转X度。
left X: X是1-359之间的整数,Fuyuneru的前进方向逆时针转X度。
forward X: X是整数(0<=X<=1000),Fuyuneru向当前朝向前进X米。
backward X: X是整数(0<=X<=1000),Fuyuneru向当前朝向后退X米。
现在祈向Fuyuneru体内输入了N(1<=N<=50)个这样的指令。可是由于此前Fuyuneru被GHQ部队击中,它出了一点小问题:这N个指令执行的顺序是不确定的。

问:Fuyuneru最远可能逃出多远?
即,Fuyuneru在执行完N条指令之后,距离原点最远的可能距离是多少?

输入格式
第一行是一个整数T,代表测试数据有T组。
每组测试数据中,第一行是一个整数N,代表指令有N条;
随后紧跟N行,每一行代表一个指令(格式保证是上述四种中的一种,数据保证合法)

输出格式
对于每组数据,输出一行:最远的可能逃亡距离,精确到小数点后3位。

输入样例

3
3
forward 100
backward 100
left 90
4
left 45
forward 100
right 45
forward 100
6
left 10
forward 40
right 30
left 10
backward 4
forward 4

输出样例

141.421
200.000
40.585

思路
此题最远距离可分为 3 部分
1.向前走
2.找出旋转角度最接近180的组合
3.向后走
4.剩下的角度不会对结果产生影响

即问题转化为 在一个数组中找 若干个数 使其和 mod 360 接近 180 (背包问题)

代码实现

bool visit[maxn];   //表示角度是否使用过
bool agl[360];      //表示能够达到这个角度

int main()
{
    freopen( "in.txt", "r", stin );

    int T;
    cin >> T;
    int k;
    string dir;
    int angle, toforward, toback;
    int d[100];
    int index;

    while( T-- )
    {
        cin >> k;
        index = 0;
        while( k-- )
        {
            cin >> dir >> angle;
            if( dir[0] == 'l' )
                d[index++] = 360-angle;
            else if( dir[0] == 'r')
                d[index++] = angle;
            else if( dir[0] == 'f')
                toforward += angle;
            else
                toback += angle;
        }
        //从d数组中 找出若干个数之和 使其和对 360取模 接近 180
        for( int i = 0; i < index; i++ )
        {
            memset( d, false; sizeof(d) );
            for( )
        }

    }
    cout << "Hello world!" << endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值