PAT甲级刷题记录-(AcWing)-Day17(基础算法 8题)

PAT甲级刷题记录-(AcWing)-Day17(基础算法 8题)

课程来源AcWing
其中AcWing中的题目为翻译好的中文题目

1091 Acute Stroke

AcWing链接
PAT链接

英语单词

解析
使用宽度优先来搜索
得到连通块的数量

注意点

#include <iostream>
#include <queue>

using namespace std;
int edge[60][1286][128];
int m, n, l, t;
struct Node {
    
    
    int x, y, z;
};
queue<Node> q;
int d[][3] = {
    
    
        {
    
    0,  0,  1},
        {
    
    0,  0,  -1},
        {
    
    0,  1,  0},
        {
    
    0,  -1, 0},
        {
    
    1,  0,  0},
        {
    
    -1, 0,  0},
};

int bfs(int x, int y, int z) {
    
    
    q.push({
    
    x, y, z});
    edge[x][y][z] = 0;
    int res = 1;
    while (!q.empty()) {
    
    
        auto node = q.front();
        q.pop();
        for (int i = 0; i < 6; ++i) {
    
    
            int a = node.x, b = node.y, c = node.z;
            a += d[i][0], b += d[i][1], c += d[i][2];
            if (a >= 0 && b >= 0 && c >= 0 && a < l && b < m && c < n && edge[a][b][c]) {
    
    
                q.push({
    
    a, b, c});
                edge[a][b][c] = 0;
                res++;
            }
        }
    }
    return res;
}

int main() {
    
    
    cin >> m >> n >> l >> t;
    for (int i = 0; i < l; ++i) {
    
    
        for (int j = 0; j < m; ++j) {
    
    
            for (int k = 0; k < n; ++k) {
    
    
                cin >> edge[i][j][k];
            }
        }
    }
    int res = 0;
    for (int i = 0; i < l; ++i) {
    
    
        for (int j = 0; j < m; ++j) {
    
    
            for (int k = 0; k < n; ++k) {
    
    
                if (edge[i][j][k]) {
    
    
                    int cnt = bfs(i, j, k);
                    if (cnt >= t) res += cnt;
                }
            }
        }
    }
    cout << res;
    return 0;
}

1148 Werewolf - Simple Version

AcWing链接
PAT链接

英语单词

解析
因为N很小只有100的数量级, 所以可以枚举, O ( n 3 ) O(n^3) O(n3)

注意点

#include <iostream>

using namespace std;
const int N = 110;
int n;
int sf[N];

int main() {
    
    
    cin >> n;
    for (int i = 1; i <= n; ++i)cin >> sf[i];
    for (int i = 1; i <= n; ++i) {
    
    
        for (int j = i + 1; j <= n; ++j) {
    
    
            int liars = 0, wolves = 0;
            // 枚举真正的狼人, 此时狼人为 i和j
            for (int k = 1; k <= n; ++k) {
    
    
                //查看有几个人在说谎, 狼人里面有几个在说谎
//                printf("i = %d, j = %d k = %d sf = %d\n", i, j, k, sf[k]);
                if (sf[k] < 0) {
    
     // k说某个人是狼人
                    // 判断k有没有说谎
                    if (sf[k] != -i && sf[k] != -j) {
    
    
                        // k说的人里面没有狼人,他说谎了
//                        printf("k = %d, sf = %d k is a liar\n", k, sf[k]);
                        liars++;
                        // 如果k是狼人,那么增加狼人中说谎的人数
                        if (k == i || k == j) wolves++;
//                        printf("liars = %d, wolves = %d\n", liars, wolves);
                    }
                } else {
    
    
                    // k说的对象是好人
                    if (sf[k] == i || sf[k] == j) {
    
    
                        // k说的好人其实是狼人, k说谎了
//                        printf("k = %d, sf = %d k is a liar\n", k, sf[k]);
                        liars++;
                        if (k == i || k == j) wolves++;
//                        printf("liars = %d, wolves = %d\n", liars, wolves);
                    }
                }
            }
//            printf("liars = %d, wolves = %d\n", liars, wolves);
            if (liars == 2 && wolves == 1) {
    
    
                cout << i << " " << j;
                return 0;
            }
        }
    }
    puts("No Solution");
    return 0;
}

1051 Pop Sequence

AcWing链接
PAT链接

英语单词

解析

注意点
插入的序列为1n, 使用一个栈s来模拟pushpop的过程
先将元素入栈, 然后检查栈头元素和给定的序列头是否相同,一直相同的话就出队 重复
结束后如果栈为空则序列合法,否则不合法

#include <iostream>
#include <stack>

const int N = 1010;
using namespace std;
int m, n, k;
int seq[N];

bool check() {
    
    
    stack<int> s;
    for (int i = 1, j = 1; i <= n; ++i) {
    
    
        s.push(i);
        if (s.size() > m) return false;
        while (!s.empty() && s.top() == seq[j] ) {
    
    
            s.pop();
            j++;
        }
    }
    return s.empty();
}

int main() {
    
    
    cin >> m >> n >> k;
    while (k--) {
    
    
        for (int i = 1; i <= n; ++i) {
    
    
            cin >> seq[i];
        }
        if (check()) puts("YES");
        else puts("NO");
    }
    return 0;
}

1055 The World’s Richest

AcWing链接
PAT链接

英语单词

解析
创建一个时间数组,记录每个age的人物链表,分别排序,最后按要求取最大值即可

注意点

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;
const int N = 210;
int n, k, m;

struct Person {
    
    
    string name;
    int age, wealth;

    bool operator<(const Person &p) const {
    
    
        if (wealth != p.wealth) return wealth > p.wealth;
        if (age != p.age) return age < p.age;
        return name < p.name;
    }
};

vector<Person> year[N];

int main() {
    
    
    cin >> n >> k;
    while (n--) {
    
    
        string name;
        int age, wealth;
        cin >> name >> age >> wealth;
        year[age].push_back({
    
    name, age, wealth});
    }
    for (auto &item:year) {
    
    
        sort(item.begin(), item.end());
    }
    for (int j = 1; j <= k; ++j) {
    
    
        cin >> m;
        int start, end;
        cin >> start >> end;
        printf("Case #%d:\n", j);
        int cnt[N];
        memset(cnt, 0, sizeof cnt);
        bool suc = false;
        while (m--) {
    
    
            int t = -1;
            for (int i = start; i <= end; ++i) {
    
    
                if (cnt[i] < year[i].size()) {
    
    
                    if (t == -1 || year[i][cnt[i]] < year[t][cnt[t]]) {
    
    
                        t = i;
                    }
                }
            }
            if (t == -1) break;
            auto &p = year[t][cnt[t]];
            cnt[t]++;
            printf("%s %d %d\n", p.name.c_str(), p.age, p.wealth);
            suc = true;
        }
        if(!suc) puts("None");
    }

    return 0;
}

!!!1057 Stack

AcWing链接
PAT链接

英语单词

解析
用两个堆来模拟

注意点

1117 Eddington Number

AcWing链接
PAT链接

英语单词

解析

注意点
这边是超过E, 第一遍写成大于等于E了

#include <iostream>
#include <algorithm>

using namespace std;
const int N = 100010;
int day[N];
int n;

int main() {
    
    
    cin >> n;
    int res = 0;
    for (int i = 1; i <= n; ++i) {
    
    
        cin >> day[i];
    }
    sort(day + 1, day + n + 1, greater<int>());
    for (int i = n; i >= 1; i--) {
    
    
        if (day[i] > i) {
    
    
            cout << i;
            return 0;
        }
    }
    puts("0");
    return 0;
}

1044 Shopping in Mars

AcWing链接
PAT链接

英语单词

解析
因为输出的是1-5这种形式,所以只要考虑哪个区间的和刚好大于等于m即可(避免考虑从左边切开链条和从右边切开链条的情况), 所以可以使用前缀和的思想,s[1]存放从1的价值,s[2]存放1-2的价值,s[n] - s[m]存放从m + 1 ~ n的价值

注意点

#include <iostream>

using namespace std;
const int N = 100010;
int n, m;
int s[N];

int main() {
    
    
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
    
    
        cin >> s[i];
        s[i] += s[i - 1]; //前缀和
        // s[1] = 1
        // s[2] = 1 - 2
        // s[n] = 1 - n
        // s[n] - s[m] = m + 1 ~ n
    }
    int res = 0x3f3f3f3f;
    for (int i = 1, j = 0; i <= n; ++i) {
    
    
        // 让j不断变大,找到大于等于m的最小值
        // 因为不知道区间里面是否存在刚好等于m的
        // 遍历 i~j之间的价值,找到第一个大于等于m的
        while (j < n && s[j] - s[i - 1] < m) j++;
        // 因为j = n的时候没判断过是否满足
        if (s[j] - s[i - 1] >= m) res = min(s[j] - s[i - 1], res);
    }
    for (int i = 1, j = 0; i <= n; ++i) {
    
    
        while (j < n && s[j] - s[i - 1] < m) j++;
        // 因为j = n的时候没判断过是否满足
        if (s[j] - s[i - 1] == res) {
    
    
            cout << i << "-" << j << endl;
        }
    }
    return 0;
}

1040 Longest Symmetric String

AcWing链接
PAT链接

解析
因为字符串在1000以内,所以可以枚举来做
使用双指针,遍历字符串,选取每一个点作为回文串的中心的,依次向两边拓展,记录最大值
枚举的时候要注意
回文串有奇数和偶数两种请客
奇数的中心点为i,左右指针为i-1,i+1
偶数的左指针为i,右指针为i+1;
所以每个点这两种情况都要枚举到

注意点

#include <iostream>

using namespace std;

int main() {
    
    
    string s;
    getline(cin, s);
    int res = 0;
    for (int i = 0; i < s.size(); ++i) {
    
    
        int l = i - 1, r = i + 1;
        while (l >= 0 && l < s.size() && r < s.size() && s[l] == s[r]) l--, r++;
        res = max(res, r - l - 1);
        l = i, r = i + 1;
        while (l >= 0 && l < s.size() && r < s.size() && s[l] == s[r]) l--, r++;
        res = max(res, r - l - 1);
    }
    cout << res << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Weary_PJ/article/details/125103550
今日推荐