All for PAT秋考 | 1124 - 1130

涉及知识

  • 1125 贪心
  • 1126 DFS判连通(并查集、BFS也可)
  • 1127 二叉树BFS(zig-zag)
  • 1129 利用set排序(避免n次重排)
  • 1130 二叉树建树、中序遍历、string(erase、pop_back)


1124 Raffle for Weibo Followers (20 分)

利用set不重复的性质、find函数。

#include <cstdio>
#include <set>
#include <string>
#include <vector>

using namespace std;
set<string> winners;
vector<string> res;
char forwards[1010][21];

int main() {
    int mm, n_skip, win1;
    scanf("%d%d%d", &mm, &n_skip, &win1);
    for (int i = 1; i <= mm; ++i)
        scanf("%s", forwards[i]);
    int curr = win1;
    while (curr <= mm) {
        while (winners.find(forwards[curr]) != winners.end())
            curr++;
        winners.insert(forwards[curr]);
        res.emplace_back(forwards[curr]);
        curr += n_skip;
    }
    if (winners.empty()) {
        printf("Keep going...\n");
    } else {
        for (auto item: res) {
            puts(item.data());
        }
    }
    return 0;
}

1125 Chain the Ropes (25 分)

  • 两段绳子每次连结,它们的长度都要折半。越早选中的绳子,折半次数越多。

  • 因此,要让最后绳长最长,就要让长绳子少折半(两个较短绳连接折半后,一定还是剩余绳子中最短的!)。

  • 策略:从小到大排序,按序连结。

#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int nn;
    scanf("%d", &nn);
    vector<double> ropes;
    double temp;
    for (int i = 0; i < nn; ++i) {
        scanf("%lf", &temp);
        ropes.emplace_back(temp);
    }
    sort(ropes.begin(), ropes.end());
    double res = ropes[0];
    int ii = 1;
    while (ii < nn) {
        res = (res + ropes[ii++]) / 2;
    }
    printf("%d\n", int(res));
    return 0;
}

1126 Eulerian Path (25 分)

  1. 输入时,建图并计算各结点的度。
  2. 判连通。(DFS、并查集、BFS均可)
  3. 按照定义判断即可。
#include <cstdio>

using namespace std;
bool graph[501][501] = {false}, visited[501] = {false};
int deg[501] = {0}, nn, mm;

void DFS(int src) {
    visited[src] = true;
    for (int i = 1; i <= nn; ++i) {
        if (!visited[i] && graph[src][i])
            DFS(i);
    }
}

int main() {
    int v1, v2;
    scanf("%d%d", &nn, &mm);
    for (int i = 0; i < mm; ++i) {
        scanf("%d%d", &v1, &v2);
        graph[v1][v2] = graph[v2][v1] = true;
        deg[v1]++, deg[v2]++;
    }
    DFS(1);
    bool connected = true;
    for (int i = 1; i <= nn; ++i) {
        if (!visited[i]) {
            connected = false;
            break;
        }
    }
    int cntOdd = 0;
    for (int i = 1; i <= nn; ++i) {
        printf("%d", deg[i]);
        printf(i == nn ? "\n" : " ");
        if (deg[i] % 2) cntOdd++;
    }
    if (!connected) puts("Non-Eulerian");
    else if (cntOdd == 0) puts("Eulerian");
    else if (cntOdd == 2) puts("Semi-Eulerian");
    else puts("Non-Eulerian");
    return 0;
}

1127 ZigZagging on a Tree (30 分)

  1. 由中序、后序序列建树,记录各深度结点数量
  2. 层序遍历,保存层序序列。
  3. 按照结点深度 (奇、偶),顺序/逆序的输出层序序列中的该层。
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;
struct Node {
    int key, depth;
    Node *lchild, *rchild;
};

int in_order[31], post_order[31], level_cnt[31] = {0};
vector<int> zz_order;

Node *createBTree(int in_st, int in_ed, int post_st, int post_ed, int depth) {
    if (in_st > in_ed || post_st > post_ed) return NULL;
    if (in_st == in_ed || post_st == post_ed) {
        level_cnt[depth]++;
        return new Node{in_order[in_st], depth, NULL, NULL};
    }
    Node *root = new Node;
    int rkey = post_order[post_ed], pos = -1;
    for (int i = in_st; i <= in_ed; i++) {
        if (in_order[i] == rkey) {
            pos = i;
            break;
        }
    }
    int lsize = pos - in_st;
    root->key = rkey;
    root->depth = depth;
    root->lchild = createBTree(in_st, pos - 1, post_st, post_st + lsize - 1, depth + 1);
    root->rchild = createBTree(pos + 1, in_ed, post_st + lsize, post_ed - 1, depth + 1);
    level_cnt[depth]++;
    return root;
}

void LevelOrder(Node *root) {
    queue<Node *> mq;
    mq.push(root);
    zz_order.emplace_back(root->key);
    while (!mq.empty()) {
        Node *curr = mq.front();
        mq.pop();
        if (curr->lchild) {
            mq.push(curr->lchild);
            zz_order.emplace_back(curr->lchild->key);
        }
        if (curr->rchild) {
            mq.push(curr->rchild);
            zz_order.emplace_back(curr->rchild->key);
        }
    }
}

int main() {
    int nn;
    scanf("%d", &nn);
    for (int i = 0; i < nn; ++i) scanf("%d", &in_order[i]);
    for (int i = 0; i < nn; ++i) scanf("%d", &post_order[i]);
    Node *root = createBTree(0, nn - 1, 0, nn - 1, 1);
    LevelOrder(root);
    int curr = 0;
    for (int i = 1; level_cnt[i]; ++i) {
        if (i % 2 == 0) { // l->r
            for (int j = 0; j < level_cnt[i]; ++j) {
                printf("%d", zz_order[curr]);
                printf(curr < nn - 1 ? " " : "\n");
                curr++;
            }
        } else { //r->l
            int t = curr;
            for (int j = level_cnt[i] - 1; j >= 0; --j) {
                printf("%d", zz_order[t + j]);
                printf(curr < nn - 1 ? " " : "\n");
                curr++;
            }
        }
    }
    return 0;
}

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

1128 N Queens Puzzle (20 分)

用不着保存整个棋盘!!!
对角线上位置的表示(diagonal):行号差的绝对值 == 列号差的绝对值
⚠️Nov. 1st二刷:若用abs函数,头文件用cstdlib,而不是cmath。

#include <cstdio>
#include <cmath>

void judgeSolution() {
    int nn;
    scanf("%d", &nn);
    int board[1001];
    bool res = true;
    for (int i = 0; i < nn; ++i) {
        scanf("%d", &board[i]);
        if (res)
            for (int j = 0; j < i; ++j) {
                if (board[j] == board[i] || (fabs(i - j) == fabs(board[i] - board[j]))) {
                    res = false;
                    break;
                }
            }
    }
    puts(res ? "YES" : "NO");
}

int main() {
    int tt;
    scanf("%d", &tt);
    for (int i = 0; i < tt; ++i) {
        judgeSolution();
    }
    return 0;
}

1129 Recommendation System (25 分)

  • 每次加入新元素就重排,复杂度将达到O(n^2 log n),由于超时,仅16分!!!
  • 应该利用set的插入、删除仅O(n log n)的特性,重载Item的小于号,注意另外保存当前的cnts数组,供res.find(Item{temp, cnts[temp]})使用,删除再插入 来更新set中记录(set中元素不可修改)!!!
#include <cstdio>
#include <set>

using namespace std;

struct Item {
    int id, cnt;

    bool operator<(const Item &i2) const {
        if (cnt != i2.cnt) return cnt > i2.cnt;
        return id < i2.id;
    }
};

int cnts[50001] = {0};
set<Item> res;

int main() {
    int nquery, max_k, temp;
    scanf("%d%d", &nquery, &max_k);
    scanf("%d", &temp);
    cnts[temp]++;
    res.insert(Item{temp, cnts[temp]});
    for (int i = 1; i < nquery; ++i) {
        scanf("%d", &temp);
        printf("%d:", temp);
        int kk = 0;
        for (auto item:res) {
            printf(" %d", item.id);
            kk++;
            if (kk == max_k) {
                printf("\n");
                break;
            }
        }
        if (kk < max_k) printf("\n");
        auto _find_ = res.find(Item{temp, cnts[temp]});
        if (_find_ != res.end()) {
            res.erase(_find_);
        }
        cnts[temp]++;
        res.insert(Item{temp, cnts[temp]});
    }
    return 0;
}
  • NOV 3 update: set的erase可以直接erase(key)
#include <cstdio>
#include <set>

using namespace std;

struct Commodity {
    int id, cnt = 1;

    bool operator<(const Commodity &c2) const {
        return cnt != c2.cnt ? cnt > c2.cnt : id < c2.id;
    }
};
int main() {
    int nq, max_rec, cnts[50001] = {0}, temp;
    scanf("%d%d", &nq, &max_rec);
    set<Commodity> rec_list;
    for (int i = 0; i < nq; ++i) {
        scanf("%d", &temp);
        if(i > 0) {
            printf("%d:", temp);
            int j = 0;
            for(auto &item: rec_list) {
                printf(" %d", item.id);
                if(++j == max_rec) break;
            }
            puts("");
        }
        rec_list.erase(Commodity{temp, cnts[temp]});
        cnts[temp]++;
        rec_list.insert(Commodity{temp, cnts[temp]});
    }
    return 0;
}

1130 Infix Expression (25 分)

中缀表达式

  • 二叉树建树、中序遍历(给孩子不为空的结点加括号)
  • string(字符/字符串连结 +=)
  • string erase(0)、pop_back()去除最外面一层括号
  • ⚠️去括号要特判树仅有一个结点的情况
#include <cstdio>
#include <string>
#include <algorithm>

using namespace std;
struct Node {
    string data;
    int lchild, rchild;
} btree[21];
int nn;
string res;

void inorder(int root) {
    if (root == -1) return;
    bool _embrace = (btree[root].lchild != -1 || btree[root].rchild != -1);
    if (_embrace) res += '(';
    if (btree[root].lchild != -1) {
        inorder(btree[root].lchild);
    }
    res += btree[root].data;
    if (btree[root].rchild != -1) {
        inorder(btree[root].rchild);
    }
    if (_embrace) res += ')';
}

int main() {
    int nn, v1, v2;
    char temp_data[12];
    bool isRoot[21];
    fill(isRoot, isRoot + 21, true);
    scanf("%d", &nn);
    for (int i = 1; i <= nn; ++i) {
        scanf("%s%d%d", temp_data, &v1, &v2);
        btree[i] = Node{temp_data, v1, v2};
        if (v1 != -1) isRoot[v1] = false;
        if (v2 != -1) isRoot[v2] = false;
    }
    int root = -1;
    for (int i = 1; i <= nn; ++i) {
        if (isRoot[i]) {
            root = i;
            break;
        }
    }
    inorder(root);
    if (nn >= 2) {
        res.erase(0, 1); //注意
        res.pop_back();
    }
    puts(res.data());
    return 0;
}
  • NOV 3 update 原来写的太麻烦了 醉了
#include <cstdio>
#include <string>
#include <algorithm>

using namespace std;
struct Node {
    string data;
    int lc, rc;
} btree[21];
int root = 1;

void in_traverse(int curr) {
    if (root != curr && btree[curr].rc != -1) printf("(");
    if (btree[curr].lc != -1) in_traverse(btree[curr].lc);
    printf("%s", btree[curr].data.data());
    if (btree[curr].rc != -1) in_traverse(btree[curr].rc);
    if (root != curr && btree[curr].rc != -1) printf(")");
}

int main() {
    int nn;
    bool isRoot[21];
    fill(isRoot, isRoot + 21, true);
    scanf("%d", &nn);
    char str[12];
    int lc, rc;
    for (int i = 1; i <= nn; ++i) {
        scanf("%s%d%d", str, &lc, &rc);
        btree[i].data = str, btree[i].lc = lc, btree[i].rc = rc;
        isRoot[lc] = isRoot[rc] = false;
    }
    while (!isRoot[root]) root++;
    in_traverse(root);
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • 一些概念 数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算,而且确保经过这...
    Winterfell_Z阅读 5,654评论 0 13
  • 涉及知识1118 并查集(模板题)1119 二叉树建树(前序、后序,唯一否?)1121 set应用,复杂度1123...
    zilla阅读 378评论 0 3
  • 涉及知识1132 sscanf(),浮点错误1133 链表重排(cmp函数、假装重排= =)1134 图的点覆盖(...
    zilla阅读 166评论 0 2
  • 计算机基础 三级存储系统的结构 计算机的三级存储系统是什么?答:计算机系统中存储层次可分为三级:高速缓冲存储器、主...
    臭墨鱼阅读 5,002评论 0 7
  • 创新,协调,绿色,开放,共享
    申论学习团阅读 35评论 0 0