PAT甲级题

1001 A+B Format (20)

输入两个整数a,b(-1000000 <= a, b <= 1000000),输出a+b,按指定格式输出,就是每三位要用”,”隔开。

简单题,printf %0nd 就是前补n个零的输出。

1002 A+B for Polynomials (25)

输入两个多项式,题目保证指数的输入是递减的。输出两个多项式的和,格式和输入时候一样。
多项式指数n<=1000,项数k<=10。

简单题。模拟即可。

1003 Emergency (25)(最短路)

给一个无向图,每个顶点有一个价值,求解从s到t有几条最短路,然后求出这几条最短路中,总价值最高的价值。

我们从根开始dfs,把每个结点的深度存下来,level[x]代表着x这个结点的深度。做完这以后,我们知道叶子结点的特点是什么,就是他没有孩子结点,那么在我们的存储方式中 等价于 G[i].size()=0。因为G[i]存储的是i这个结点的孩子节点。所以dfs的过程中发现G[i].size()==0就可以在这一层的计数器上+1了,也就是cnt[lv]++。

#include <bits/stdc++.h>
using namespace std;
const int maxn_v = 500 + 5;
const int INF = 0x3f3f3f3f;
typedef pair<int, int>pii;

struct Edge{int to, w;};
vector<Edge>G[maxn_v];

int people[maxn_v], dis[maxn_v], vis[maxn_v], path[maxn_v], gather[maxn_v];
void dijkstra(int vs, int es, int s, int t)
{
    for(int i = 0; i < vs; i++)    dis[i] = INF, vis[i] = 0, path[i] = 1, gather[i] = people[i];
    priority_queue<pii, vector<pii>, greater<pii>>que;

    dis[s] = 0;
    que.push({0, s});

    while(que.size())
    {
        pii cur = que.top();que.pop();
        int u = cur.second, w = cur.first;
        if(vis[u])  continue;
        vis[u] = 1;
        for(auto o : G[u])
        {
            if(dis[u] + o.w < dis[o.to])
            {
                dis[o.to] = dis[u] + o.w;
                que.push({o.to, dis[o.to]});
                path[o.to] = path[u];

                if(gather[o.to] < gather[u] + people[o.to])
                {
                    gather[o.to] = gather[u] + people[o.to];
                }
                que.push({dis[o.to], o.to});
            }
            else if(dis[u] + o.w == dis[o.to])
            {
                path[o.to] += path[u];
                if(gather[o.to] < gather[u] + people[o.to])
                {
                    gather[o.to] = gather[u] + people[o.to];
                }
            }
        }
     }
    cout << path[t] <<  " " << gather[t] << endl;
}

int main()
{
    int vs, es, s, t;
    scanf("%d%d%d%d", &vs, &es, &s, &t);
    for(int i = 0; i < vs; i++)    scanf("%d", &people[i]);
    for(int i = 0; i < es; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        G[u].push_back({v, w});
        G[v].push_back({u, w});
    }
    dijkstra(vs, es, s, t);
    return 0;
}

1004 Counting Leaves (30)(dfs)

给你一棵有根数,问这棵树每一层叶子结点的数量,结点数量n<=500.

n这么小,直接搜就行了

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100 +5;
typedef pair<int, int>pii;

int maxlv;
int level[maxn];
int cnt[maxn];
vector<int>G[maxn];

void dfs(int cur, int lv)
{
    level[cur] = lv;
    maxlv = max(maxlv, lv);
    if(G[cur].size() == 0)  cnt[lv]++;//如果它没有孩子,说明它这一层没有孩子的结点数++
    for(auto o : G[cur])   dfs(o, lv + 1);
}

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    while(m--)
    {
        int pa, num;
        scanf("%d%d", &pa, &num);
        while(num--)
        {
            int ch;
            scanf("%d", &ch);
            G[pa].push_back(ch);
        }
    }
    maxlv = 0;
    dfs(1, 0);
    for(int i = 0; i <= maxlv; i++)
    {
        printf("%d%c", cnt[i], i == maxlv ? '\n' : ' ');
    }
    return 0;
}

1005 Spell It Right (20)

出一个不大于10^100数,将各位数字相加的和用英文输出。

1006 Sign In and Sign Out (25)

给出n个人的id、sign in时间、sign out时间,求最早进来的人和最早出去的人的ID。(id长度<15)

把每个人sign in,sign out的时间都算出来,存一下,排序两次即可。

1007 Maximum Subsequence Sum (25)(最大字段和)

求最大子段和,输出最大的和以及这个子段的开始值和结束值。如果所有数都小于0,那么认为最大的和为0,并且输出首尾元素。

经典dp。细节略微小心一下即可。有些许坑点。

1008 Elevator (20)

有一个电梯上下跑,电梯升高一层需要6秒,下降一层需要4秒。每次停下电梯将花费5秒。一开始电梯在0层,有n次请求,每次请求后电梯会跑到那一层,最后电梯不需要回到底层。问总共花了多少时间,所有数据范围<=100。

1009 Product of Polynomials (25)

多项式乘法,多项式长度n<=1000.

模拟即可。

1010 Radix (25)(难题)
1011 World Cup Betting (20)

给出三行数据,代表三场比赛。每行有三个浮点整数,从左至右分别代表W(Win)、T(Tie)、L(Lost)。现在需要从每行的 W、T、L 中选择最大的数,并输出三行各自选择的是哪一个。并输出(三个数相乘*0.65-1)*2,保留两位小数。

1012 The Best Rank (25)

已知n名考生的ID,c语音,数学,英语成绩,进行m次查询,输出给定ID的学生,在三门课或者平均成绩中获得的最高排名,以及哪一门。

1013 Battle Over Cities (25)(并查集or深搜)

从一个无向图里头,取出一个顶点,至少要补几条边能够使得它联通。

  我们画几个图就很容易明白,n个结点如果想要联通,必然至少需要n-1条边。那么如果是n个块(一个块有若干个联通的结点)呢,是不是也是如此。这里就有一个连通分量的概念。然后我们怎么去看有几个块呢,显然并查集和dfs都是极好的。
  这里只讲dfs,其实题目很简单,就是最入门的dfs题,想一下刚学dfs时候的八连通,四联通的题目,只需要dfs和vis标记即可。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 +5;
typedef pair<int, int>pii;

int attack;
int vis[maxn];
vector<int>G[maxn];

void dfs(int cur)
{
    vis[cur] = 1;
    for(auto o : G[cur])    if(vis[o] == 0 && o != attack) dfs(o);
}

int main()
{
    int vs, es, query;
    scanf("%d%d%d", &vs, &es, &query);

    while(es--)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);//无向图建图
        G[v].push_back(u);
    }

    while(query--)
    {
        int x;
        scanf("%d", &x);
        attack = x;
        //计算联通分量
        memset(vis, 0, sizeof(vis));
        int scc = 0;
        for(int i = 1; i <= vs; i++)
        {
            if(i == attack || vis[i]) continue;//如果已经被攻占,或者已经被dfs过了,跳过
            dfs(i);
            scc++;
        }
        printf("%d\n", scc - 1);
    }
    return 0;
}

1014 Waiting in Line (30)(挺繁琐的模拟)

n个窗口,每个窗口可以排m人。有k位顾客需要办理业务,给出了每个客户的办理业务时间。银行在8点开始服务,如果窗口都排满了,客户就得在黄线外等候。如果有一个窗口用户服务结束,黄线外的客户就进来一个。如果有多个可选,选窗口id最小的。输出查询客户的服务结束时间。

1015 Reversible Primes (20)

给定两个数N,D。如若N是素数,并且N在D进制下翻转,并转化成10进制还是素数,那么输出YES

进制转换+质数判断

1016 Phone Bills (25)(繁琐的模拟)

n个人的通话记录,然后给你每个时间段的话费单价,让你求出每个用户每个月的电话账单

1017 Queueing at Bank (25)(繁琐的模拟)

有n个客户和k个窗口,给出n个客户的到达时间和需要的时长。有空闲的窗口就去办理,没有的话就需要等待,求客户的平均时长。如果在8点前来的,就需要等到8点。如果17点以后来的,则不会被服务,无需考虑。

1018 Public Bike Management (30)

给一张图, 每个节点都代表一个杭州的一个借或者还自行车站点, 节点上的值表示当前这个站点拥有多少辆自行车, 每条边表示两个站点之间要花多少时间从一个站点到另一个站点, 给定一个有问题的站点, 求出从控制中心到该站点的最短路径并且使得带出去以及拿回来的自行车的数量最少.、

1019 General Palindromic Number (20)

求数N在b进制下其序列是否为回文串,并输出其在b进制下的表示。
进制转换

1020 Tree Traversals (25)

树的遍历序列转换。给出二叉树的后序遍历和中序遍历,求层次遍历。
递归建树。大白书经典题。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 500 +5;

typedef pair<int, int>pii;
int post[35], in[35], lch[35], rch[35];
int build(int L1, int R1, int L2, int R2)//in中序遍历 [L1,R1], post后序遍历[L2,R2]
{
    if(L1 > R1) return -1;
    int root = post[R2];
    int p = L1;
    while(in[p] != root)    p++;//推算出根节点在中序遍历中的位置。
    int cnt = p - L1;

    lch[root] = build(L1, p - 1, L2, L2 + cnt - 1);//建立左子树
    rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1);//建立右子树
    return root;
}

void level_order(int root)//层序遍历
{
    queue<int>que;
    que.push(root);
    while(que.size())
    {
        int cur = que.front();que.pop();
        int lson = lch[cur], rson = rch[cur];
        if(lson != -1)  que.push(lson);
        if(rson != -1)  que.push(rson);
        printf("%d%c", cur, que.size() ? ' ' : '\n');
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &post[i]);
    for (int i = 0; i < n; i++) scanf("%d", &in[i]);
    int root = build(0, n - 1, 0, n - 1);
    level_order(root);
    return 0;
}

1021 Deepest Root (25)

给出n个点和n-1条边。若是只有一个连通分量,且为无环图,则可将其看成一棵树,求拥有最大深度的树的所有根,并按字典序升序输出。否则输出连通块的数目。

  这是比前两个dfs稍微难一点的dfs。其实就是树的直径问题,求解树的直径,我们是使用dfs的方式,我们先从任意一个点dfs,找到深度最深的点,在开始dfs,找到深度最深的点,这个时候深度就是树的直径了。
  dfs_scc就是找联通分块的函数,其实就是1013的翻版。
  dfs_level就是用temp数组来保存深度最深的节点有哪些。然后挑任意一个点开始第二次dfs_level,temp数组即为答案。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10000 +5;

int maxLevel;
int vis[maxn];
int level[maxn];
vector<int>G[maxn];
vector<int>temp;

void dfs_scc(int cur)
{
    vis[cur] = 1;
    for(auto o : G[cur])    if(vis[o] == 0) dfs_scc(o);
}

void dfs_level(int cur, int pa, int lv)
{//深搜层数
    level[cur] = lv;
    if(lv > maxLevel)
    {
        maxLevel = lv;
        temp.clear();
        temp.push_back(cur);
    }
    else if(lv == maxLevel)
    {
        temp.push_back(cur);
    }

    for(auto o : G[cur])
    {
        if(o != pa)
        {
            dfs_level(o, cur, lv + 1);
        }
    }
}

int main()
{
    int vs;
    scanf("%d", &vs);
    for(int i = 1; i < vs; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);//无向图建图10
        G[v].push_back(u);
    }

    int scc = 0;
    for(int i = 1; i <= vs; i++)
    {
        if(vis[i] == 0) dfs_scc(i), scc++;
    }

    if(scc != 1)
    {
        printf("Error: %d components\n", scc);
    }
    else
    {
        set<int>ans;
        //第一次dfs
        maxLevel = 0;
        temp.clear();
        memset(level, 0, sizeof(level));
        dfs_level(1, -1, 0);
        int root = temp[0];

        for(auto o : temp)  ans.insert(o);

        //第二次dfs
        maxLevel = 0;
        temp.clear();
        memset(level, 0, sizeof(level));
        dfs_level(root, -1, 0);
        root = temp[0];

        for(auto o : temp)  ans.insert(o);

        for(auto o : ans)
        {
            printf("%d\n", o);
        }
    }
    return 0;
}

1022 Digital Library (30)(繁琐的模拟)

1023 Have Fun with Numbers (20)

将给出的一个大数*2,判断其是否可由原来的数通过排列得到。

大数乘法的简略版。

1024 Palindromic Number (25)

给出一个<=10^10的数,每次将其颠倒后与原数相加,若结果为回文数,则输出对应的数和颠倒的次数。

大数加法

1025 PAT Ranking (25)(模拟模拟)

有若干子测试,每个子测试中有ki个人,给出其编号和成绩。现在需要你给出最终的成绩排名,给出每个人的编号、最终排名、子测试序号、子测试排名。

1026 Table Tennis (30)(挺繁琐的模拟)

有k个台球桌,其中有m个为VIP桌。该台球室营业时间为9:00:00到21:00:00。有若干pair来该台球室打球。如果台球桌已满人,否则使用编号最小的台球桌。这些人当中有VIP用户。如果在等待时有个台球桌刚好空出来,且为VIP桌,则VIP用户可率先使用,有多个VIP用户时按到达时间的顺序使用。给出该台球室按每个桌子的开始服务时间排序的使用情况(所服务pair的到来时间、开始服务时间、等待时间),并给出每个桌子服务pair数目。

1027 Colors in Mars (20)

题意:把给出的3个十进制数转为3个2为13进制数。

进制转换

1028 List Sorting (25)

给出一些学生的ID、姓名、等级,按照某一列排序并输出结果。

简单模拟排序即可

1029 Median (25)

给两个递增数列,找出合并以后非递减排序状态下的中位数
简单题。

1030 Travel Plan (30)

给定有权无向图,找出起点到终点权值最小的最短路。

1031 Hello World for U (20)

给一个字符串,输出一个最接近正方形的U形串
简单模拟。

1032 Sharing (25)

给定两个单词,它们的字母按照链表形式相连并给出地址,找出它们开始重合的那个节点的地址。

链表。用map模拟一下就好。

1033 To Fill or Not to Fill (25)

1034 Head of a Gang (30)

给定一系列的带权连通图,要求其中总权值超过K,节点大于3的图的个数以及其中该子图中权值最大的节点。

1035 Password (20)

给定一些账号和密码,改掉密码中的一些特定字符,并按要求输出

简单模拟。

1036 Boys vs Girls (25)

给定一些人物信息,要找到男生成绩最差和女生成绩最好,并求这两者差距

简单模拟

1037 Magic Coupon (25)

给你两组数,每组拿出一个数,两两相乘直到全部用完,求最大的结果是多少。

1038 Recover the Smallest Number (30)

给你n个数字串,问你能组成的最小数是多少,前导0不算

1039 Course List for Student (25)

有n名学生和k门课程,给出每门课程的编号和选修这门课程的人数以及名字,求每名学生选修的课程数以及课程编号。
简单模拟。

1040 Longest Symmetric String (25)

求最长对称字串的长度。串的长度只有1000

经典dp。

1041 Be Unique (20)

给你n个数,求出第一个只出现了一次的数。

1042 Shuffling Machine (20)

一副扑克,本来是按顺序摆放的,从1-54,给你k,代表要洗牌k次,给你54个数,代表每次洗牌要把i位置的牌洗到a[i]位置,求洗牌k次后这副牌的顺序。

简单模拟。

1043 Is It a Binary Search Tree (25)

让你判断一下这棵树是否是BST。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 +5;
typedef pair<int, int>pii;

struct node
{
    int val;
    node *left, *right;
    node():left(NULL), right(NULL){}
};
int pre[maxn];//二叉搜索树的先序序列

bool judge(int L, int R, int k)
{
    if(L >= R)  return true;
    int p = L + 1;
    if(k == 0)
    {
        while(p <= R && pre[p] < pre[L])  p++;//左子树小于根节点

        for(int i = p; i <= R; i++)
        {
            if(pre[i] < pre[L]) return false;
        }
    }
    else if(k == 1)//BST的镜像
    {
        while(p <= R && pre[p] >= pre[L]) p++;
        for(int i = p; i <= R; i++)
        {
            if(pre[i] >= pre[L])    return false;
        }
    }

    return judge(L + 1, p - 1, k) && judge(p, R, k);
}

node *build(int L, int R, int k)
{
    if(L > R)  return NULL;

    node *root = new node();
    root->val = pre[L];

    int p = L + 1;
    if(k == 0)
    {
        while(p <= R && pre[p] < pre[L])  p++;//左子树小于根节点
    }
    else if(k == 1)//BST的镜像
    {
        while(p <= R && pre[p] >= pre[L]) p++;
    }
    root->left = build(L + 1, p - 1, k);
    root->right = build(p, R, k);
    return root;
}
void post_order(node *x, node *root)
{
    if(x->left != NULL) post_order(x->left, root);
    if(x->right != NULL)    post_order(x->right, root);

    printf("%d", x->val);

    if(x != root)   printf(" ");
    else printf("\n");
}

void solve(int n)
{
    if (judge(0, n - 1, 0))
    {
        puts("YES");
        node *root = build(0, n - 1, 0);
        post_order(root, root);
        return ;
    }
    if (judge(0, n - 1, 1))
    {
        puts("YES");
        node *root = build(0, n - 1, 1);
        post_order(root, root);
        return ;
    }

    puts("NO");
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &pre[i]);
    }
    solve(n);

    return 0;
}

1044 Shopping in Mars (25)

火星人购物使用钻石链,每颗钻石都有一定的价值。付款是,要求从钻石链上找到所有刚好能匹配到商品价值的连续的钻石子链,如果没有, 则找到超过商品价值的最小的钻石子链。

1045 Favorite Color Stripe (30)

最长公共子序列变形

猜你喜欢

转载自blog.csdn.net/qq_29556211/article/details/79721227