首页 > 技术文章 > PAT (Advanced Level) 1140~1143:1140模拟 1141模拟 1142暴力 1143 BST+LCA

tyty-Somnuspoppy 2018-08-23 13:52 原文

1140 Look-and-say Sequence(20 分)

意:观察序列D, D1, D111, D113, D11231, D112213111, ...,显然后一个串是对前一个串每一小段连续相同的字母及其个数的描述。例如,D112213111是对D11231的描述,原因是在D11231中,依次出现了1个D(即D1),2个1(即12),1个2(即21),1个3(即31),1个1(即11), 连起来即为D112213111。给定D,问符合该规律的序列中第N个数是多少?

分析:

1、C++写法:按题意模拟即可。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
int main(){
    int D, N;
    while(scanf("%d%d", &D, &N) == 2){
        char tmp[1010];
        sprintf(tmp, "%d", D);
        string s = string(tmp);
        string ans;
        N--;
        while(N--){
            int len = s.size();
            int cnt = 0;
            ans = "";
            for(int i = 0; i < len - 1; ++i){
                if(s[i] == s[i + 1]){
                    ++cnt;
                }
                else{
                    ans += s[i];
                    sprintf(tmp, "%d", cnt + 1);
                    ans += string(tmp);
                    cnt = 0;
                }
            }
            if(s[len - 2] == s[len - 1]){
                ans += s[len - 2];
                sprintf(tmp, "%d", cnt + 1);
                ans += string(tmp);
            }
            else{
                ans += s[len - 1];
                ans += "1";
            }
            s = ans;
        }
        printf("%s\n", s.c_str());
    }
    return 0;
}

2、python写法:itertools.groupby函数可以将字符串中连续相同的字母分组。

import itertools
D, N = map(int, input().split())
s = str(D)
for _ in range(N - 1):
    ans = ''
    for char, lst in itertools.groupby(s):
        ans += char
        ans += str(len(tuple(lst)))
    s = ans
print(s)
1141 PAT Ranking of Institutions(25 分)

题意:根据给定的信息计算学校的排名,并按规定的顺序输出即可。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<map>
#include<iostream>
using namespace std;
const int MAXN = 100000 + 10;
map<string, int> mp;
int cnt;
struct Node{
    int B, A, T, tot, sum, _rank;
    string school;
    bool operator < (const Node&rhs)const{
        return sum > rhs.sum || sum == rhs.sum && tot < rhs.tot || sum == rhs.sum && tot == rhs.tot && school < rhs.school;
    }
}num[MAXN];
int getId(string s){
    if(mp.count(s)) return mp[s];
    return mp[s] = ++cnt;
}
int main(){
    int N;
    while(scanf("%d", &N) == 1){
        cnt = 0;
        mp.clear();
        string Rank, School;
        int Score;
        for(int i = 0; i < N; ++i){
            cin >> Rank >> Score >> School;
            int len = School.size();
            for(int j = 0; j < len; ++j){
                if(School[j] >= 'A' && School[j] <= 'Z') School[j] += 32;
            }
            int id = getId(School);
            if(Rank[0] == 'B') num[id].B += Score;
            else if(Rank[0] == 'A') num[id].A += Score;
            else if(Rank[0] == 'T') num[id].T += Score;
            ++num[id].tot;
            num[id].school = School;
        }
        for(int i = 1; i <= cnt; ++i){
            double tmp = num[i].B / 1.5 + num[i].A + num[i].T * 1.5;
            num[i].sum = (int)tmp;
        }
        sort(num + 1, num + cnt + 1);
        printf("%d\n", cnt);
        printf("1 %s %d %d\n", num[1].school.c_str(), num[1].sum, num[1].tot);
        num[1]._rank = 1;
        int kase = 1;
        for(int i = 2; i <= cnt; ++i){
            if(num[i].sum != num[i - 1].sum){
                num[i]._rank = i;
                printf("%d %s %d %d\n", num[i]._rank, num[i].school.c_str(), num[i].sum, num[i].tot);
            }
            else{
                num[i]._rank = num[i - 1]._rank;
                printf("%d %s %d %d\n", num[i]._rank, num[i].school.c_str(), num[i].sum, num[i].tot);
            }
        }
    }
    return 0;
}
1142 Maximal Clique(25 分)

题意:如果一个无向子图中任意两个不同的点都直接相邻,则称其为clique;若该clique不能通过增加其他任何点来使其仍是clique,则称其为maximal clique。给定一个无向图,判断给定的点集是否满足maximal clique。

分析:

1、最多200个点,记录边的信息,暴力即可。

2、对于判断是否为maximal clique,则暴力枚举每个可能增加的点,判断其是否与给定点集中的所有点都直接相邻即可。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<map>
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 200 + 10;
int Edge[MAXN][MAXN];
vector<int> v;
bool vis[MAXN];
int Nv, Ne;
bool judge(){
    int len = v.size();
    for(int i = 0; i < len; ++i){
        for(int j = i + 1; j < len; ++j){
            int tmpx = v[i];
            int tmpy = v[j];
            if(!Edge[tmpx][tmpy] && !Edge[tmpy][tmpx]){
                return false;
            }
        }
    }
    return true;
}
string solve(){
    int len = v.size();
    for(int i = 1; i <= Nv; ++i){
        if(!vis[i]){
            bool ok = true;
            for(int j = 0; j < len; ++j){
                int tmpx = v[j];
                if(!Edge[i][tmpx] && !Edge[tmpx][i]){
                    ok = false;
                    break;
                }
            }
            if(ok) return "Not Maximal";
        }
    }
    return "Yes";
}
int main(){
    while(scanf("%d%d", &Nv, &Ne) == 2){
        memset(Edge, 0, sizeof Edge);
        int a, b;
        for(int i = 0; i < Ne; ++i){
            scanf("%d%d", &a, &b);
            Edge[a][b] = Edge[b][a] = 1;
        }
        int M;
        scanf("%d", &M);
        while(M--){
            memset(vis, false, sizeof vis);
            v.clear();
            int K, x;
            scanf("%d", &K);
            while(K--){
                scanf("%d", &x);
                v.push_back(x);
                vis[x] = true;
            }
            bool ok = judge();
            if(!ok){
                printf("Not a Clique\n");
            }
            else{
                printf("%s\n", solve().c_str());
            }
        }
    }
    return 0;
}

1143 Lowest Common Ancestor(30 分)

题意:给定一个二叉搜索树,求给定的一对点的最近公共祖先。树的键值在int范围内。

分析:

1、常规思路:离散化树的键值,建BST,在树上求LCA,结果超时。

2、假设待求lca的一对点分别为u和v,遍历给定BST的前序遍历数组,若当前遍历的点值在u和v之间或者值等于u或v,则其必为u和v的最近公共祖先。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<map>
#include<iostream>
#include<vector>
#include<set>
using namespace std;
const int MAXN = 10000 + 10;
int a[MAXN];
map<int, int> mp;
bool judge(int tmp, int x, int y){
    return tmp == x || tmp == y || (tmp > x && tmp < y) || (tmp > y && tmp < x);
}
int main(){
    int M, N;
    while(scanf("%d%d", &M, &N) == 2){
        mp.clear();
        for(int i = 0; i < N; ++i){
            scanf("%d", &a[i]);
            mp[a[i]] = 1;
        }
        int x, y;
        while(M--){
            scanf("%d%d", &x, &y);
            if(!mp.count(x) && !mp.count(y)){
                printf("ERROR: %d and %d are not found.\n", x, y);
            }
            else if(!mp.count(x)){
                printf("ERROR: %d is not found.\n", x);
            }
            else if(!mp.count(y)){
                printf("ERROR: %d is not found.\n", y);
            }
            else{
                for(int i = 0; i < N; ++i){
                    if(judge(a[i], x, y)){
                        if(a[i] == x){
                            printf("%d is an ancestor of %d.\n", a[i], y);
                        }
                        else if(a[i] == y){
                            printf("%d is an ancestor of %d.\n", a[i], x);
                        }
                        else{
                            printf("LCA of %d and %d is %d.\n", x, y, a[i]);
                        }
                        break;
                    }
                }
            }
        }
    }
    return 0;
}

  

推荐阅读