23.5.31 22数据结构阶段测试1补题

7-3 冰岛人

分数 25                                                                                               提交通过率  0/166(0.00%)

2018年世界杯,冰岛队因1:1平了强大的阿根廷队而一战成名。好事者发现冰岛人的名字后面似乎都有个“松”(son),于是有网友科普如下:

冰岛人沿用的是维京人古老的父系姓制,孩子的姓等于父亲的名加后缀,如果是儿子就加 sson,女儿则加 sdottir。因为冰岛人口较少,为避免近亲繁衍,本地人交往前先用个 App 查一下两人祖宗若干代有无联系。本题就请你实现这个 App 的功能。

输入格式:

输入首先在第一行给出一个正整数 N(1<N≤105),为当地人口数。随后 N 行,每行给出一个人名,格式为:名 姓(带性别后缀),两个字符串均由不超过 20 个小写的英文字母组成。维京人后裔是可以通过姓的后缀判断其性别的,其他人则是在姓的后面加 m 表示男性、f 表示女性。题目保证给出的每个维京家族的起源人都是男性。

随后一行给出正整数 M,为查询数量。随后 M 行,每行给出一对人名,格式为:名1 姓1 名2 姓2。注意:这里的是不带后缀的。四个字符串均由不超过 20 个小写的英文字母组成。

题目保证不存在两个人是同名的。

输出格式:

对每一个查询,根据结果在一行内显示以下信息:

  • 若两人为异性,且五代以内无公共祖先,则输出 Yes
  • 若两人为异性,但五代以内(不包括第五代)有公共祖先,则输出 No
  • 若两人为同性,则输出 Whatever
  • 若有一人不在名单内,则输出 NA

所谓“五代以内无公共祖先”是指两人的公共祖先(如果存在的话)必须比任何一方的曾祖父辈分高。

输入样例:

15
chris smithm
adam smithm
bob adamsson
jack chrissson
bill chrissson
mike jacksson
steve billsson
tim mikesson
april mikesdottir
eric stevesson
tracy timsdottir
james ericsson
patrick jacksson
robin patricksson
will robinsson
6
tracy tim james eric
will robin tracy tim
april mike steve bill
bob adam eric steve
tracy tim tracy tim
x man april mikes

输出样例:

Yes
No
No
Whatever
Whatever
NA

一些知识:

一、map.count()

map.count()返回的是0或1

0表示查找失败
1表示map中存在该键

二、map.find()

map.find()返回的是迭代器

如果查找成功,则返回该键所在位置的迭代器
失败则返回map.end()所在位置的迭代器

三、string.back()

返回string的最后一个字符

#include<bits/stdc++.h>
using namespace std;
typedef pair<bool, string> pbs;
int n, m;
map<string, pbs> mp;
string s1, s2, tmp;
void check(string s1, string s2) {
    int ct1 = 0, ct2;
    while (s1 != "") {
        tmp = s2;
        ct2 = 0;
        while (tmp != "") {
            if (s1 == tmp && (ct1 < 4 || ct2 < 4)) {
                puts("No");
                return;
            }
            if (ct1 >= 4 && ct2 >= 4) {
                puts("Yes");
                return;
            }
            tmp = mp[tmp].second;
            ct2++;
        }
        s1 = mp[s1].second;
        ct1++;
    }
    puts("Yes");
    return;
}
int main() {
    cin >> n;
    while (n--) {
        cin >> s1 >> s2;
        if (s2.back() == 'n') mp[s1] = { 1, s2.substr(0, s2.size() - 4) };
        else if (s2.back() == 'r') mp[s1] = { 0, s2.substr(0, s2.size() - 7) };
        else if (s2.back() == 'm') mp[s1].first = 1;
        else mp[s1].first = 0;
    }
    cin >> m;
    while (m--) {
        cin >> s1 >> tmp >> s2 >> tmp;
        if (!mp.count(s1) || !mp.count(s2)) puts("NA");
        else if (mp[s1].first == mp[s2].first) puts("Whatever");
        else check(s1, s2);
    }
    return 0;
}

呼~~~补完啦 小总结:题目刷太少 知识点掌握不全面 考试状态不好。

7-5 玩转二叉树

分数 3 / 25                                                                                                提交通过率 6/197(3.05%)

给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
1 2 3 4 5 6 7
4 1 3 2 6 5 7

输出样例:

4 6 1 7 5 3 2

 妈的这题做过的,考试的时候算下标算死了醉了。

#include<bits/stdc++.h>
using namespace std;
typedef struct TNode* tree;
struct TNode {
    int data;
    tree l, r;
};
const int N = 100;
int n, in[N], pre[N];
vector<int> v;
tree Create(int inl, int prel, int len) {
    if (len == 0) {
        return NULL;
    }
    tree bt = new TNode;
    int i, l, r = pre[prel];
    bt->data = r;
    for (i = inl; i < inl + len; ++i)
        if (in[i] == r) break;
    l = i - inl;
    bt->l = Create(inl, prel + 1, l);
    bt->r = Create(inl + l + 1, prel + 1 + l, len-l-1);
    return bt;

}
void level(tree t) {
    queue<tree> q;
    q.emplace(t);
    while (q.size()) {
        tree tmp = q.front(); q.pop();
        if (tmp->r) q.emplace(tmp->r);
        if (tmp->l) q.emplace(tmp->l);
        v.emplace_back(tmp->data);
    }
}
int main() {
    cin >> n;
    for (int i = 0; i < n; ++i) cin >> in[i];
    for (int i = 0; i < n; ++i) cin >> pre[i];
    tree t = Create(0, 0, n);
    level(t);
    for (int i = 0; i < v.size(); ++i) {
        if (i) cout << ' ' << v[i];
        else cout << v[i];
    }
    return 0;
}

7-6 完全二叉树的层序遍历

分数 25                                                                                                                        3/228(1.32%)

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树

给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。

输入格式:

输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。

输出格式:

在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

8
91 71 2 34 10 15 55 18

输出样例:

18 34 55 71 2 10 15 91

这题纯纯送分,因为他是完全二叉树,所以只要模拟递归一下后序遍历并存入数组,妈的考试没做到傻蛋了。 

#include<bits/stdc++.h>
using namespace std;
const int N = 50;
int n, t[N];
void dfs(int i){
    if(i*2 <= n) dfs(i*2);
    if(i*2+1 <= n) dfs(i*2+1);
    cin >> t[i];
}
int main(){
    cin >> n;
    dfs(1);
    for(int i = 1; i <= n; ++i){
        cout << t[i];
        if(i < n) cout << ' ';
    }
    return 0;
}

7-7 家庭房产

分数 25                                                                                                        提交通过率 0/67(0.00%)

给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数、人均房产面积及房产套数。

输入格式:

输入第一行给出一个正整数N(≤1000),随后N行,每行按下列格式给出一个人的房产:

编号 父 母 k 孩子1 ... 孩子k 房产套数 总面积

其中编号是每个人独有的一个4位数的编号;分别是该编号对应的这个人的父母的编号(如果已经过世,则显示-1);k(0≤k≤5)是该人的子女的个数;孩子i是其子女的编号。

输出格式:

首先在第一行输出家庭个数(所有有亲属关系的人都属于同一个家庭)。随后按下列格式输出每个家庭的信息:

家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积

其中人均值要求保留小数点后3位。家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。

输入样例:

10
6666 5551 5552 1 7777 1 100
1234 5678 9012 1 0002 2 300
8888 -1 -1 0 1 1000
2468 0001 0004 1 2222 1 500
7777 6666 -1 0 2 300
3721 -1 -1 1 2333 2 150
9012 -1 -1 3 1236 1235 1234 1 100
1235 5678 9012 0 1 50
2222 1236 2468 2 6661 6662 1 300
2333 -1 3721 3 6661 6662 6663 1 100

输出样例:

3
8888 1 1.000 1000.000
0001 15 0.600 100.000
5551 4 0.750 100.000
#include<bits/stdc++.h>
using namespace std;
const int N = 10000;
bool fg[N];
int a[N];
int n, k, id, dad, mom, son, num, sum, ct;
struct node {
    int num, sum;
};
map<int, node> mp;
vector<int> v[N];
struct P {
    int id, peo;
    double avg1, avg2;
    P(int a, int b, double c, double d) {
        id = a; peo = b; avg1 = c; avg2 = d;
    }
    bool operator < (const P& p) const {
        if (avg2 == p.avg2) return id < p.id;
        else return avg2 > p.avg2;
    }
};
set<P> st;
int Find(int x) {
    if (a[x] < 0) return x;
    else return Find(a[x]);
}
void Union(int x, int y) {
    int r1 = Find(x);
    int r2 = Find(y);
    if (r1 < r2) {
        a[r1] += a[r2];
        a[r2] = r1;
        mp[r1].num += mp[r2].num;
        mp[r1].sum += mp[r2].sum;
    }
    else if (r2 < r1) {
        a[r2] += a[r1];
        a[r1] = r2;
        mp[r2].num += mp[r1].num;
        mp[r2].sum += mp[r1].sum;
    }
}
int main() {
    for (int i = 0; i < N; ++i) a[i] = -1;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> id >> dad >> mom >> k;
        v[i].emplace_back(id);
        v[i].emplace_back(dad);
        v[i].emplace_back(mom);
        while (k--) {
            cin >> son;
            v[i].emplace_back(son);
        }
        cin >> num >> sum;
        mp[id].num = num;
        mp[id].sum = sum;
    }
    for (int i = 0; i < n; ++i) {
        id = v[i][0]; fg[id] = 1;
        for (int j = 1; j < v[i].size(); ++j) {
            if (v[i][j] != -1) { Union(id, v[i][j]); fg[v[i][j]] = 1; }
        }
    }
    for (int i = 0; i < N; ++i) {
        if(fg[i])
            if (a[i] < 0) {
                ct++;
                //cout << mp[i].num << ' ' << mp[i].sum << ' ' << i << endl;
                st.insert(P(i, -a[i], 1.0 * mp[i].num / (-a[i]), 1.0 * mp[i].sum / (-a[i])));
            }
    }
    printf("%d\n", ct);
    for (auto e : st) {
        printf("%04d %d %.3lf %.3lf\n", e.id, e.peo, e.avg1, e.avg2);
    }
    return 0;
}

加班到12点 就是复杂版并查集 主要是他的房子数量 和面积是后面给出来的 就很难受 得先存起来 不然后面mp[id]并查集合并的时候没法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值