PAT(甲级)2019年冬季考试 7-1 Good in C (20分) 7-2 Block Reversing (25分) 7-3 Summit (25分) 7-4 Cartesian Tree (

7-1 Good in C (20分)

读题比较麻烦,实际不难,注意输出格式就可以了。

#include<cstdio>
#include<vector>
#include<iostream>
#include<queue>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;

vector<vector<string> > vab;
vector<string> ca;
string str, temp;

int main() {
    for (int i = 0; i < 26; i++) {
        ca.clear();
        for (int j = 0; j < 7; j++) {
            cin >> str;
            ca.push_back(str);
        }
        vab.push_back(ca);
    }
    getchar();
    getline(cin, str);
    temp = {};
    ca.clear();
    for (int i = 0; i < str.size(); i++) {
        if (str[i] >= 'A' && str[i] <= 'Z') {
            temp += str[i];
        }
        else if (temp.size() != 0) {
            ca.push_back(temp);
            temp.clear();
        }
    }
    if (temp.size() != 0) {
        ca.push_back(temp);
    }
    for (int i = 0; i < ca.size(); i++) {
        for (int col = 0; col < 7; col++) {
            for (int j = 0; j < ca[i].size(); j++) {
                int t = ca[i][j] - 'A';
                cout << vab[t][col];
                if (j != ca[i].size() - 1) printf(" ");
                else printf("\n");
            }
        }
        if (i != ca.size() - 1) printf("\n");
    }
    return 0;
}

7-2 Block Reversing (25分)

静态数组,多做就不难。

#include<cstdio>
#include<vector>
#include<iostream>
#include<queue>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;

#define maxn 100100

struct node {
    int data, address, block, inside;
    node(int d, int a, int b, int i) : data(d), address(a), block(b), inside(i) {}
    bool operator < (const node &a) const {
        if (a.block != block) return block > a.block;
        else return inside < a.inside;
    }
};
int N, K, firstaddress;
int data[maxn], nest[maxn];
vector<node> v;

int main() {
    scanf("%d %d %d", &firstaddress, &N, &K);
    int a, b, c;
    for (int i = 0; i < N; i++) {
        scanf("%d %d %d", &a, &b, &c);
        data[a] = b;
        nest[a] = c;
    }
    int ta = firstaddress;
    int blockcount = 0, insidecount = 0;
    while(ta != -1) {
        v.push_back(node(data[ta], ta, blockcount, insidecount));
        insidecount++;
        if (insidecount == K) {
            insidecount = 0;
            blockcount++;
        }
        ta = nest[ta];
    }
    sort(v.begin(), v.end());
    for (int i = 0; i < v.size(); i++) {
        if (i != v.size() - 1) printf("%05d %d %05d\n", v[i].address, v[i].data, v[i + 1].address);
        else printf("%05d %d -1\n", v[i].address, v[i].data);
    }
    return 0;
}

7-3 Summit (25分)

将每个area的邻近结点都放入temp中存储,采用set存储,以确保所有的结点只出现一次。

然后,对area的每一个结点,将temp中不存在于他的邻近结点中的删除。得到一个包含area所有结点的最小连通图(不太确定名词对不对,但是就是题目所说的最佳安排)。

将最佳安排temp和area进行比较就可以输出了。

注意:

temp中需要加入area所有结点,否则有一些结点只有单一个就会出错。

temp中删除结点时,不删除检查的当前结点,否则导致错误。

#include<cstdio>
#include<vector>
#include<iostream>
#include<queue>
#include<cmath>
#include<string>
#include<algorithm>
#include<set>
using namespace std;

#define maxn 205

set<int> g[maxn];
int N, M, K, L;
set<int> area, temp;
set<int>::iterator it, jt;

int main() {
    scanf("%d %d", &N, &M);
    int a, b;
    while(M--) {
        scanf("%d %d", &a, &b);
        g[a].insert(b);
        g[b].insert(a);
    }
    scanf("%d", &K);
    for (int i = 0; i < K; i++) {
        area.clear();
        temp.clear();
        scanf("%d", &L);
        while(L--) {
            scanf("%d", &a);
            area.insert(a);
            temp.insert(a);
            for (it = g[a].begin(); it != g[a].end(); it++) {
                temp.insert(*it);
            }
        }
        for (it = area.begin(); it != area.end(); it++) {
            vector<int> v;
            for (jt = temp.begin(); jt != temp.end(); jt++) {
                int t = *jt;
                if (t == *it) continue;
                if (0 == g[*it].count(*jt)) v.push_back(*jt);
            }
            for (int k = 0; k < v.size(); k++) {
                temp.erase(v[k]);
            }
        }
        if (temp == area) {
            printf("Area %d is OK.\n", i + 1);
        }
        else if (temp.size() > area.size()) {
            printf("Area %d may invite more people, such as ", i + 1);
            for (it = temp.begin(); it != temp.end(); it++) {
                if (area.count(*it) == 0) {
                    printf("%d.\n", *it);
                    break;
                }
            }
        }
        else printf("Area %d needs help.\n", i + 1);
    }
    return 0;
}

7-4 Cartesian Tree (30分)

咋一看很麻烦,其实很简单。

就是将每个区域的最小点作为根,然后根据这个点分成两个区域,再在每个区域重复当前步骤。

上面得到一棵树,接着层次遍历,搞定。

#include<cstdio>
#include<vector>
#include<iostream>
#include<queue>
#include<cmath>
#include<string>
#include<algorithm>
#include<set>
using namespace std;

vector<int> input, out;
struct node {
    int data;
    node *left, *right;
};

node* build(int left, int right) {
    if (left >= right) return NULL;
    node* root = new node;
    int minone = left, i;
    for (i = left + 1; i < right; i++) {
        if (input[i] < input[minone]) minone = i;
    }
    root->data = input[minone];
    root->left = build(left, minone);
    root->right = build(minone + 1, right);
    return root;
}

void level(node *root) {
    queue<node*> q;
    q.push(root);
    while(!q.empty()) {
        node* temp = q.front();
        q.pop();
        out.push_back(temp->data);
        if (temp->left != NULL) q.push(temp->left);
        if (temp->right != NULL) q.push(temp->right);
    }
    return;
}

int main() {
    int a, N;
    scanf("%d", &N);
    for (int i = 0; i < N; i++) {
        scanf("%d", &a);
        input.push_back(a);
    }
    node *root = build(0, N);
    level(root);
    for (int i = 0; i < N; i++) {
        printf("%d", out[i]);
        if (i != N - 1) printf(" ");
        else printf("\n");
    }
    return 0;
}

总结

这次的题目个人感觉没有特别多的思考量,都是比较基础的应用,而且没有什么坑,这是最难得的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值