AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

2013机试题

作者: 作者的头像   Jaryn上岸 ,  2023-03-18 19:18:01 ,  所有人可见 ,  阅读 40


0


题目链接: https://www.acwing.com/blog/content/32375/

一. 字符串匹配

kmp,机试先考虑用find

#include <bits/stdc++.h>

using namespace std;

/**
 * Author :Jaryn
 * Time :2023/3/17 3:34 下午
 * Desc :对于主串M和模式串P,找到P在M中出现的所有子串
            的第一个字符在P中的位置。
            P中第一个字符所在的位置为0。
            首行的数字表示有多少组字符串。
 */

int main() {
    string sstr, pstr;
    int x;
    cin >> x;
    while (x--) {
        cin >> (sstr) >> (pstr);
        int n = sstr.size(), m = pstr.size();
        vector<char> s(n + 1), p(m + 1);
        for(int i = 0; i < n; i++) s[i + 1] = sstr[i]; // 转为下标从1开始
        for(int i = 0; i < n; i++) p[i + 1] = pstr[i];
        vector<int> ne(m + 1);

        for (int i = 2, j = 0; i <= m; i++) {
            while (j && p[i] != p[j + 1]) j = ne[j];
            if (p[i] == p[j + 1]) j++;
            ne[i] = j;
        }
        for (int i = 1, j = 0; i <= n; i++) {
            while (j && s[i] != p[j + 1]) j = ne[j];
            if (s[i] == p[j + 1]) j++;
            if (j == m) {
                cout << i - j << " ";
                j = ne[j];
            }
        }
        cout << endl;
    }
    return 0;
}

二. AFamousICPCTeam

#include <bits/stdc++.h>

using namespace std;

/**
 * Author :Jaryn
 * Time :2023/3/17 3:34 下午
 * Desc :给出四个正方体箱子的边长,问能装下这四个正方体箱子
    的大正方体边长最小要多大,要求边长最小且必须能装下四个箱子。

 */

int main() {
    int a,b,c,d;
    cin >> a >> b >> c >> d;
    // 22组合的最大值
    int ans = -1;
    ans = max(ans, a + b);
    ans = max(ans, a + c);
    ans = max(ans, a + d);
    ans = max(ans, b + c);
    ans = max(ans, b + d);
    ans = max(ans, c + d);
    cout << ans;
    return 0;
}

三. A famous grid(螺旋矩阵)

http://acm.hdu.edu.cn/showproblem.php?pid=4255
思路:
先用筛法,找出101*101内的素数(因为输入的两点值限制是一万内);之后去填满数组arr[101][101],像图片中那样从arr[50][50](也就是1)开始填起,如果是素数就填-1表示这个路径不通,否则填入相应的数字;之后用bfs找出最短路径
可以用一个数组存储PII,数组下标是对应的值,内容是对应的下标

填满数组的具体思路:观察可知,1先向右边走1步生成2,再向上走1步生成3,| 再向左走2步生成4/5,再向下走2步生成6/7 | 再向右边走3步生成8/9/10,再向上走3步生成11/12/13....
可知:先是右上各走1,左下各走2,右上各走3,可利用一个bool变量表示是右上还是左下,自增变量表示步长,当生成的数大于1万就可以停止。

#include <bits/stdc++.h>

using namespace std;

/**
 * Author :Jaryn
 * Time :2023/3/18 6:34 下午
 * Desc :在螺旋矩阵中,问两个位置(不能经过素数位置)之间的最短距离是多少
 * 思路:先用筛法,找出101*101内的素数(因为输入的两点值限制是一万内);
 * 之后去填满数组arr[110][110],像图片中那样从arr[50][50](也就是1的位置)开始填起,
 * 如果是素数就填-1表示这个路径不通,否则填入相应的数字;之后用bfs找出最短路径(走迷宫)
 *
 */
typedef pair<int, int> PII;
const int N = 20010;
int primes[N];
bool flag[N]; // false表示是素数
int g[110][110], cnt;
PII pos[N]; // 数组下标是矩阵的值,内容是对应的下标


void lineSelect() {
    flag[1] = true; // 1不是素数
    for (int i = 2; i <= 10000; i++) {
        if (!flag[i]) primes[cnt++] = i;
        for (int j = 0; i * primes[j] <= 10000; j++) {
            flag[i * primes[j]] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

void generateSpiralArray() {
    // 具体思路:观察可知,1先向右边走1步生成2,再向上走1步生成3,| 再向左走2步生成4/5,再向下走2步生成6/7 | 再向右边走3步生成8/9/10,再向上走3步生成11/12/13....
    // 可知:先是右上各走1,左下各走2,右上各走3,可利用一个bool变量表示是右上还是左下,
    // 自增变量表示步长,当生成的数大于1万就可以停止。
    pos[1] = {50, 50}; // 只要是中心位置就可,49,49也行,通过pos下标已经对应好了
    g[50][50] = 1;
    int num = 1;
    int len = 1; // 步长
    bool direct = true; // true就是右上,false就是左下
    PII start = {50, 50};
    while (num <= 10000) {
        if (direct) { // 右 + 上,走len步
            // 右走len步
            int x = start.first, y = start.second;
            for (int i = 1; i <= len; i++) {
                y++;
                num++;
                pos[num] = {x, y};
                g[x][y] = flag[num] ? num : -1;
            }
            // 上走len步
            for (int i = 1; i <= len; i++) {
                x--;
                num++;
                pos[num] = {x, y};
                g[x][y] = flag[num] ? num : -1;
            }
            start = {x, y};
            direct = false;
            len++;
        } else {
            // 左 + 下
            int x = start.first, y = start.second;
            // 左
            for (int i = 1; i <= len; i++) {
                y--;
                num++;
                pos[num] = {x, y};
                g[x][y] = flag[num] ? num : -1; // 质数存-1
            }
            // 下走len步
            for (int i = 1; i <= len; i++) {
                x++;
                num++;
                pos[num] = {x, y};
                g[x][y] = flag[num] ? num : -1;
            }
            start = {x, y};
            direct = true;
            len++;
        }
    }
}

int bfs(int startNum, int endNum) {
    PII start = pos[startNum];
    PII end = pos[endNum];
    queue<PII> q;
    q.push(start);
    int dist[110][110]; // 存储从 start出发的最短路径
    memset(dist, -1, sizeof dist);
    dist[start.first][start.second] = 0;

    int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, -1, 1};
    while (q.size()) { // 遇到-1就不能通过
        PII c = q.front();
        q.pop();

        int x = c.first;
        int y = c.second;
        if (x == end.first && y == end.second) {
            return dist[x][y];
        }
        for (int i = 0; i < 4; i++) {
            int nX = x + dx[i];
            int nY = y + dy[i];
            if (nX >= 0 && nX < 110 && nY >= 0 && nY < 110 && dist[nX][nY] == -1
                && g[nX][nY] != -1) {
                dist[nX][nY] = dist[x][y] + 1;
                q.push({nX, nY});
            }
        }
    }
    return -1;
}

int main() {
    // 线性筛法
    lineSelect();
    // 生成螺旋数组
    generateSpiralArray();
    // bfs
    int start, end;
    while (cin >> start >> end) {
        int res = bfs(start, end);
        if (res == -1) cout << "impossible";
        else cout << res << endl;

    }
    return 0;
}

0 评论

你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息