模拟题

STL常用函数

【刷题】刷题常用STL函数整理合集_达瓦里氏吨吨吨的博客-CSDN博客_stl常用函数

image-20220906120435032

【set】集合

基本操作
set<int> a;            //声明

a.begin();            //返回指向第一个元素的迭代器
a.end();              //返回指向超尾的迭代器
a.clear();            //清空容器a
a.empty();            //判断容器是否为空
a.size();             //返回当前容器元素个数
a.count(x);           //返回容器a中元素x的个数
a.insert(x);          //插入元素,其中a为set<T>型容器,x为T型变量

了解
a.insert(first,second);       //其中first为指向区间左侧的迭代器,second为指向右侧的迭代器。作用是将first到second区间内元素插入到a(左闭右开)。
a.erase(x):删除建值为x的元素
a.erase(first,second):删除first到second区间内的元素(左闭右开)
a.erase(iterator):删除迭代器指向的元素
注:set中的删除操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意。
lower_bound(x1):返回第一个不小于键参数x1的元素的迭代器
upper_bound(x2):返回最后一个大于键参数x2的元素的迭代器
由以上俩个函数,可以得到一个目标区间,即包含集合中从'x1'到'x2'的所有元素
set_union():对集合取并集
set_intersection():对集合取交集,它的接口与set_union()相同。

【map && unordered_map】映射

在这里插入图片描述

遍历map:

for (auto& [k, v] : m) {
    cout << k << " " << v << endl;
}

for(auto iter = m.begin(); iter!=m.end(); iter ++){
    cout << iter.first << " " << iter.second << 
}

【heap】最大堆和最小堆

void testHeap() 
{
    vector<int> data{ 3,1,2,7,5 };
    //构造堆,最大堆
    make_heap(data.begin(), data.end(), less<int>());
    //pop堆顶元素,最大的元素
    pop_heap(data.begin(), data.end(), less<int>());
    cout << data.back() << endl;//输出7
    data.pop_back();
    //往堆中添加元素
    data.push_back(4);
    push_heap(data.begin(), data.end(), less<int>());//调整堆
    //排序
    sort_heap(data.begin(), data.end(), less<int>());
    for (int x : data)
        cout << x << " ";
    cout << endl;//输出 1,2,3,4,5
}

排版问题

1473 - 字符棱形

题目:

输入一个整数n表示棱形的对角半长度,请你用*把这个棱形画出来。

输入:

1

输出:
*
输入:

3

输出:
  *
 ***
*****
 ***
  *

思路

  • 分上下两部分。
  • 枚举每一行的空格数、*数和行号i的关系,找规律。

代码

#include <bits/stdc++.h>

using namespace std;

int n; 

int main(int argc, char** argv) {    
    cin >> n;
    for(int i = 0; i < n; i ++){
        int j = n - 1 - i;
        for(int k = 0; k < j;k ++)cout << " ";
        for(int k = 0; k < 2 * i + 1; k ++)cout << "*";
        cout << endl;
    }
    for(int i = 0; i < n - 1; i ++){
        for(int k = 0; k < i + 1; k ++)cout << " ";
        for(int k = 0; k < (n - 1 - i) * 2 - 1;k ++)cout << "*";
        cout << endl;
    }
    return 0;
    
}

1392 - 杨辉三角形 - 西北工业大学

题目:

打印杨辉三角:

代码

#include <iostream>

using namespace std;

const int N = 2010;

int c[N][N];
int n;

void init()
{
    for (int i = 0; i < N; i++)
        for (int j = 0; j <= i; j++)
            if (!j)
                c[i][j] = 1;
            else
                c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
}

int main()
{
    init();
    int n;
    scanf("%d", &n);
    for (int i = 1; i < n; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            printf("%d ", c[i][j]);
        }
        printf("\n");
    }
    return 0;
}

1377 - 旋转矩阵 - 北航

题目:

任意输入两个9阶以下矩阵,要求判断第二个是否是第一个的旋转矩阵,如果是,输出旋转角度(0、90、180、270),如果不是,输出-1。 要求先输入矩阵阶数,然后输入两个矩阵,每行两个数之间可以用任意个空格分隔。行之间用回车分隔,两个矩阵间用任意的回车分隔。

输入样例:
3
1 2 3
4 5 6
7 8 9
7 4 1
8 5 2
9 6 3
输出样例:
90

代码:

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 14;

int a[N][N], b[N][N], c[N][N];
int n;

bool ab_is_same() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (a[i][j] != b[i][j])
                return false;
        }
    }
    return true;
}

void rotate() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            c[j][n - 1 - i] = a[i][j];
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            a[i][j] = c[i][j];
        }
    }
}

int main() {
    while (scanf("%d", &n) != EOF) {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                scanf("%d", &a[i][j]);

        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                scanf("%d", &b[i][j]);

        bool flag = false;
        for (int i = 0; i <= 3; i++) {
            if (!flag) {
                if (ab_is_same()) {
                    cout << i * 90 << endl;
                    flag = true;
                } else {
                    rotate();
                }
            }
        }
        if (!flag)
            cout << "-1" << endl;
    }
    return 0;
}

1216 - 旋转方阵

题目:

打印出一个旋转方阵,见样例输出。

输入样例:
5
输出样例:
1   16  15  14  13
2   17  24  23  12
3   18  25  22  11
4   19  20  21  10
5   6   7   8   9

代码:

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 22;

int a[N][N];
bool st[N][N];
int n;

int main() {
    scanf("%d", &n);
    //下右上左
    int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
    int tot = n * n;
    int i = 0, j = 0, cnt = 1;
    int d = 0;
    while (tot--) {
        a[i][j] = cnt++;
        st[i][j] = true;
        int ni = i + dx[d], nj = j + dy[d];
        if (ni < 0 || nj < 0 || ni >= n || nj >= n || st[ni][nj]) {
            d = (d + 1) % 4;
            ni = i + dx[d], nj = j + dy[d];
        }
        i = ni, j = nj;
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%-3d", a[i][j]);
            //-表示左对齐,3表示输出宽度默认是3位,
            //如果变量n的宽度小于3,则在后面补空格,
            //如果多于3位,则按n的实际位数输出。
        }
        printf("\n");
    }

    return 0;
}

1221 - 旋转矩阵

题目:

旋转方阵是一个有n行m列的矩阵,每个矩阵格子里有一个数字。 同样地,旋转方阵有3种操作: 操作1:将方阵顺时针旋转90度 操作2:将方阵沿纵向对称轴翻折 操作3:将方阵逆时针旋转90度 现在将对方阵进行k次操作,输出最后的方阵状态。

思路

  • n行数;m列数

  • 顺时针90°:(i,j)->(j, n-1-i)

  • 沿纵向对称轴翻折:(i, j)->(i, m-1-j)

  • 逆时针90°:(i,j)->(m-1-j, i)

代码

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 110;

int a[N][N], b[N][N];
int n, m, k;


void opera(int o) {
    if (o == 1) {
        //顺时针旋转矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                b[j][n - 1 - i] = a[i][j];
            }
        }
        swap(n, m);

    } else if (o == 2) {
        //将矩阵对称
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                b[i][j] = a[i][m - 1 - j];
            }
        }

    } else if (o == 3) {
        //逆时针旋转矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                b[m - 1 - j][i] = a[i][j];
            }
        }
        swap(n, m);
    }
    
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            a[i][j] = b[i][j];
}

int main() {
    while (scanf("%d%d%d", &n, &m, &k) != EOF) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf("%d", &a[i][j]);
            }
        }
        while (k--) {
            int o;
            scanf("%d", &o);
            opera(o);
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                printf("%d ", a[i][j]);
            }
            printf("\n");
        }
    }

    return 0;
}

1472 - 2048游戏

题目:

2048游戏是一个4*4矩阵,用户可以按上下左右4个方向键让所有的方块向同一个方向运动,两个相同数字方块撞一起之后合并成为他们的和,每次操作之后随即生成一个2或者4.
合并规则:相邻会碰撞的两个数字合并且一个位置只会触发一次合并,并且优先合并移动方向顶部的位置

输入样例:
1
0 0 0 2
0 0 0 2
0 0 4 8
0 0 4 8
输出样例:
0 0 8 4
0 0 0 16
0 0 0 0
0 0 0 0

思路:

以up函数为例:

  • 先进行合并操作:逐列进行遍历,若当前列的当前元素下面的第一个非零元素和自己一样,则把当前元素乘2,下面那个元素归零。
  • 然后把每一列向上移,覆盖了0元素。

代码:

虽然有150+行,但是up,down,left,right四个函数高度对称,都是vscode中的 github Copilot插件自动生成的,太强了。。。

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 6;

int a[N][N], b[N][N];
int op;

void up() {
    for (int j = 1; j <= 4; j++) {
        for (int i = 1; i <= 3; i++) {
            for (int t = i + 1; t <= 4; t++) {
                if (a[t][j] == 0)
                    continue;
                if (a[i][j] != a[t][j])
                    break;
                if (a[i][j] == a[t][j]) {
                    a[i][j] *= 2;
                    a[t][j] = 0;
                    break;
                }
            }
        }
    }
    for (int j = 1; j <= 4; j++) {
        int k = 1;
        for (int i = 1; i <= 4; i++) {
            if (a[i][j]) {
                a[k++][j] = a[i][j];
            }
        }
        for (int i = k; i <= 4; i++) {
            a[i][j] = 0;
        }
    }
}

void down() {
    for (int j = 1; j <= 4; j++) {
        for (int i = 4; i >= 2; i--) {
            for (int t = i - 1; t >= 1; t--) {
                if (a[t][j] == 0)
                    continue;
                if (a[i][j] != a[t][j])
                    break;
                if (a[i][j] == a[t][j]) {
                    a[i][j] *= 2;
                    a[t][j] = 0;
                    break;
                }
            }
        }
    }

    for (int j = 1; j <= 4; j++) {
        int k = 4;
        for (int i = 4; i >= 1; i--) {
            if (a[i][j]) {
                a[k--][j] = a[i][j];
            }
        }
        for (int i = k; i >= 1; i--) {
            a[i][j] = 0;
        }
    }
}
void left() {
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 3; j++) {
            for (int t = j + 1; t <= 4; t++) {
                if (a[i][t] == 0)
                    continue;
                if (a[i][j] != a[i][t])
                    break;
                if (a[i][j] == a[i][t]) {
                    a[i][j] *= 2;
                    a[i][t] = 0;
                    break;
                }
            }
        }
    }
    for (int i = 1; i <= 4; i++) {
        int k = 1;
        for (int j = 1; j <= 4; j++) {
            if (a[i][j]) {
                a[i][k++] = a[i][j];
            }
        }
        for (int j = k; j <= 4; j++) {
            a[i][j] = 0;
        }
    }
}
void right() {
    for (int i = 1; i <= 4; i++) {
        for (int j = 4; j >= 2; j--) {
            for (int t = j - 1; t >= 1; t--) {
                if (a[i][t] == 0)
                    continue;
                if (a[i][j] != a[i][t])
                    break;
                if (a[i][j] == a[i][t]) {
                    a[i][j] *= 2;
                    a[i][t] = 0;
                    break;
                }
            }
        }
    }
    for (int i = 1; i <= 4; i++) {
        int k = 4;
        for (int j = 4; j >= 1; j--) {
            if (a[i][j]) {
                a[i][k--] = a[i][j];
            }
        }
        for (int j = k; j >= 1; j--) {
            a[i][j] = 0;
        }
    }
}

int main() {
    cin >> op;
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; j++) {
            cin >> a[i][j];
        }
    }
    switch (op) {
        case 1:
            up();
            break;
        case 2:
            down();
            break;
        case 3:
            left();
            break;
        case 4:
            right();
            break;
    }
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

日期问题

日期问题三板斧:

const int months[13] = {
    0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

int is_leap_year(int year) {
    if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
        return 1;
    return 0;
}

int days_of_month(int year, int month) {
    if(month == 2) return months[month] + is_leap_year(year);
    return months[month];
}

1051 - 日期计算

题目:

定义一个结构体变量(包括年、月、日),编程序,要求输入年月日,计算并输出该日在本年中第几天。

输入样例:
1985 1 20
2006 3 12
输出样例:
20
71

代码:

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int months[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int is_leap_year(int year) {
    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}

int days_of_months(int year, int month) {
    if (month == 2 && is_leap_year(year)) {
        return 29;
    }
    return months[month];
}

int main() {
    int year, month, day;
    while (cin >> year >> month >> day) {
        if(year < 0 || month < 1 || month > 12 || day < 1 || day > days_of_months(year, month)) {
            cout << "Input error!" << endl;
            continue;
        }
        int days = 0;
        for (int i = 1; i < month; i++) {
            days += days_of_months(year, i);
        }
        days += day;
        cout << days << endl;
    }
    return 0;
}

1011 - 日期

今天是2012年4月12日星期四,编写程序,输入今天开始到12月31日之间的任意日期,输出那一天是星期几。例如输入“5(回车)20(回车)”(5月20日),输出应为“Sunday”。

思路:

先算出来目标日期和今天差几天,方法:

加入今天4月12,目标日期12月20.

那么从4月加到11月,得到的总和天数为到12月12日的天数,在加上12月12日到12月20日有几天。

得到总的天数之后,摩7,再加当前星期(周日第0天,则周四是4),再摩7,就是12月20日的星期。

代码:

#include <algorithm>
#include <cstdio>
#include <iostream>

using namespace std;

const int months[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int is_leap_year(int year) {
    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}

int days_of_months(int year, int month) {
    if (month == 2 && is_leap_year(year)) {
        return 29;
    }
    return months[month];
}

string weeks[7] = {"Sunday",   "Monday", "Tuesday", "Wednesday",
                   "Thursday", "Friday", "Saturday"};

int main() {
    int now_year = 2012, now_month = 4, now_day = 12, now_week = 4;
    int month, day;
    scanf("%d %d", &month, &day);
    int days = 0;
    for (int i = now_month; i < month; i++) {
        days += days_of_months(now_year, i);
    }
    days += day - now_day;
    int week = now_week + days % 7;
    if (week > 6) {
        week -= 7;
    }
    printf("%s\n", weeks[week].c_str());
    return 0;
}

输出

排序问题

1151 - 成绩排序

查找和排序

题目:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩
都按先录入排列在前的规则处理。

示例:
jack 70
peter 96
Tom 70
smith 67

从高到低 成绩
peter 96
jack 70
Tom 70
smith 67

从低到高

smith 67

jack 70
Tom 70
peter 96

输入描述:

输入多行,先输入要排序的人的个数,然后输入排序方法0(降序)或者1(升序)再分别输入他们的名字和成绩,以一个空格隔开

输出描述:

按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开

要用稳定排序stable_sort()

#include <bits/stdc++.h>

using namespace std;

const int N = 1010;

struct Student {
    string name;
    int grade;
} s[N];

bool cmpDesc(Student a, Student b) {
    return a.grade > b.grade;
}

bool cmpAsc(Student a, Student b) {
    return a.grade < b.grade;
}

int main() {
    int n, order;
    while (cin >> n) {
        cin >> order;
        for (int i = 0; i < n; i++) {
            cin >> s[i].name >> s[i].grade;
        }
        if (order == 0) {
            stable_sort(s, s + n, cmpDesc);
        } else {
            stable_sort(s, s + n, cmpAsc);
        }
        for (int i = 0; i < n; i++) {
            cout << s[i].name << " " << s[i].grade << endl;
        }
    }
    return 0;
}

1010 - 排序

输入n个数进行排序,要求先按奇偶后按从小到大的顺序排序

输入样例:

8
1 2 3 4 5 6 7 8

输出样例:

1 3 5 7 2 4 6 8
#include <bits/stdc++.h>

using namespace std;

const int N = 1010;

int a[N];

bool cmp(int a, int b) {
    if (a % 2 == b % 2)  //同奇或同偶,则小的在前
        return a < b;
    return (a % 2 > b % 2);  //奇数排在偶数前面
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    sort(a, a + n, cmp);
    for (int i = 0; i < n; ++i) {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

模拟题:

1726. 挤奶顺序 - AcWing题库

题目大意:

有2种限制条件:几头牛有相对位置,几头牛有固定位置

现在放1号牛,问最靠前能放到哪?

思路:

有三种牛:有固定位置,有相对位置,既没有固定位置也没有相对位置

对应1号牛的三种情况。

代码:

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

using namespace std;

const int N = 110;

int n, m, k;
int q[N];
int p[N];
bool st[N];

/**
 * 有三种牛:有固定位置,有相对位置,既没有固定位置也没有相对位置
 * 对应1号牛的三种情况。
 */
 

int main()
{
    cin >> n >> m >> k;
    bool flag = false;
    for(int i = 1; i <= m; i ++){
        cin >> q[i];
        if(q[i] == 1)flag = true;
    }
    memset(p, -1, sizeof p);
    for(int i = 0; i < k; i ++){
        int a, b;
        cin >> a >> b;
        //第一种情况,1的位置是固定的,那么直接输出
        if(a == 1){
            cout << b << endl;
            return 0;
        }
        //p[a] = b: 牛a的位置固定到b
        //st[b] = true : 位置b有牛了
        p[a] = b;
        st[b] = true;
    }
    
    //flag = true:第二种情况,1的位置相对于另几头牛是固定的
    if(flag){
        //把相对位置固定的牛从前往后放,即牛q[i]放到j的
        for(int i = 1, j = 1; i <= m; i ++){
            while(st[j])j ++;
            //如果牛q[i]已经有了固定的位置,接下来的有相对位置的牛都要从这头牛的后面开始放
            //即:另j从这头牛的位置开始
            if(p[q[i]] != -1)j = p[q[i]];
            else{
                if(q[i] == 1){
                    cout << j << endl;
                    return 0;
                }
                //把j这个位置设为有牛,把牛q[i]放到j这个位置,j往后移
                st[j] = true;
                p[q[i]] = j;
                j ++;
            }
        }
    }
    //第三种情况,1的位置不固定,也没有相对关系
    //把有相对位置的牛从后往前放,然后从前往后找空地方,找到的第一个空地方放1号牛
    else{
        for(int i = m, j = n;i;i --){
            while(st[j])j --;
            //牛q[i]已经有了固定位置,那么更新j从q[i]的位置开始
            if(p[q[i]] != -1)j = p[q[i]];
            else{
                st[j] = true;
                j --;
            }
        }
        
        for(int i = 1;i <= n; i ++){
            if(!st[i]){
                cout << i << endl;
                return 0;
            }
        }
    }
    return 0;
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1149440709@qq.com

×

喜欢就点赞,疼爱就打赏