蓝桥杯刷题回顾

【大数要在过程中取余】

【蓝桥杯-结果填空】斐波那契数列_It's the Climb-CSDN博客

要注意在中间就取余,否则会造成数据溢出报错。

【动态规划 - 拖累法】

【蓝桥杯-动态规划】求最大子段和+最大子矩阵和_It's the Climb-CSDN博客

·拖累法的适用场景:位置相邻地更新最优解(比如最大子段和、最大子矩阵和)

·拖累法的核心思想:dp[i]表示当前的最优解。如果dp[i-1]拖累了当前(比如dp[i-1]<0),则将当前值作为该步的最优解dp[i],否则上一步就是有帮助的,dp[i]=dp[i-1]+当前值。

·对于最大子矩阵和来说,复杂度为O(n^3),因为要遍历子矩阵的行头、行尾和列尾。(列头是在遍历列尾的过程中被动态规划给隐含更新的)。

·给数组清零:memset(A, 0, sizeof(A));

#include<iostream>
#include<string.h>
using namespace std;

int main()
{
    int A[51][51] = {0};
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>A[i][j];
        }
    }
    
    int dp[51] = {0};
    int sum_col[51] = {0};
    int max_res = -1e6;
    for(int i=1; i<=n; i++)  //子矩阵行头
    {
        memset(sum_col, 0, sizeof(sum_col)); // 清零
        for(int j=i; j<=n; j++)  //子矩阵行尾
        {
            for(int k=1; k<=m; k++)  //列
            {
                sum_col[k] += A[j][k];
                if(dp[k-1] > 0)
                {
                    dp[k] = dp[k-1] + sum_col[k];
                }
                else
                {
                    dp[k] = sum_col[k];
                }
                if(max_res < dp[k])
                {
                    max_res = dp[k];
                }
            }
        }
    }
    cout<<max_res<<endl;
    return 0;
}

【四平方和】

·暴力解法也要注意优化:只需要遍历三个数,因为第四个数可相减计算出来;遍历是可以设置上限的!

·万能头文件

#include<bits/stdc++.h>

·排序

  1. 定义:vector<int> outputs;
  2. 加入:outputs.push_back(a);
  3. 排序:sort(outputs.begin(), outputs.end());

【大数加法】

【蓝桥杯-基础训练】A+B_It's the Climb-CSDN博客

·char数组存储大数

  1. 初始化:char A[501], B[501] = {0};   // 这里初始化为0,实际ASCII码是'\0',代表字符数组的终结符
  2. 输入:scanf("%s%s", A, B);    //采用scanf
  3. 计算实际长度:int len_A = strlen(A);   //strlen函数判断的唯一标准是'\0'
  4. 字符取出来转数字:a1 = A[1] - '0';
  5. 直接存元素为数字类型:A[1] = 5;   
  6. 如果直接存元素为数字类型,输出要注意明确类型:prinf("%d", A[1]);   //不能直接用cout,否则输出的是实际的ASCII码而非我们要的数值!
  7. 如果直接存元素为数字类型,之后就不能用strlen了,因为如果有个数字0,就相当于终结符了。

·常识:两个n位数相加,结果最多为n+1位数。

【交叉排序】

主要是要了解vector<int>(容器)的用法——很方便进行排序!。

  1. 定义: vector<int> A;
  2. 入栈:A.push_back(a);
  3. 排序:sort(A.begin(), A.end());  注意是前闭后开的。对其中某一段进行排序可以是sort(A.begin()+l1-1, A.begin()+r1);   同时注意默认从小到大排序。
  4. 打印栈顶:cout<<A.back();
  5. 打印栈顶后紧接一个出栈操作:A.pop_back();
  6. 如果是想按原有输入顺序来输出,则在步骤4、5之前先调整整体的顺序:reverse(A.begin(), A.end());

其实就是很形象地理解嘛,push_back就是插到末尾,而back()就是取最末尾的元素,pop_back就是把最末尾的元素去掉。

#include<iostream>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    int N, l1, r1, l2, r2;
    cin>>N>>l1>>r1>>l2>>r2;
    vector<int> A;
    int temp;
    for(int i=0; i<N; i++)
    {
        cin>>temp;
        A.push_back(temp); //进栈
    }
    //排序 由于i从1开始,所以要-1. 前闭后开
    sort(A.begin()+l1-1, A.begin()+r1);
    sort(A.begin()+l2-1, A.begin()+r2);
    
    //由于默认排序从小到大 所以要颠倒下后者的顺序
    reverse(A.begin()+l2-1, A.begin()+r2);
    //由于要求顺序输出,所以给栈颠倒一下,这样出栈就是按原有顺序啦
    reverse(A.begin(), A.end());
    
    //输出结果
    cout<<A.back();
    A.pop_back();
    while(!A.empty())
    {
        cout<<" "<<A.back();
        A.pop_back();
    }
    
    return 0;
}

同时也要灵活采用stack<int> 栈(遵循先进后出):

  1. 定义:stack<int> S;
  2. 进栈:S.push(a);
  3. 出栈:S.pop(a);
  4. 打印栈顶元素:cout<<S.top();

【机器人】

【蓝桥杯-基础训练】机器人_It's the Climb-CSDN博客

自己写了个新思路,根据每次的state来进行判断,也就是对四个方向进行分类讨论,针对性地处理“转向”的问题。

这里要回忆起来,C++是不支持函数返回多个数值的,所以需要采用传址,in-place修改数值

1. 函数定义:

int forward(int *state, int *x, int *y, int step)

   在方法体里修改值,也是带*,表示取的是这个地址对应的数值,从而实现修改。

2. 函数调用(传地址):

forward(&state, &x, &y, step);

具体代码(每个状态自己模拟了下应该怎么走):

#include<iostream>
#include<bits/stdc++.h>
using namespace std;

int forward(int *state, int *x, int *y, int step)
{
    if(*state==1)
        *x -= step;
    else if(*state==2)
        *y += step;
    else if(*state==3)
        *x += step;
    else if(*state==4)
        *y -= step;
    return 0;
}

int back(int *state, int *x, int *y, int step)
{
    if(*state==1)
    {
        *x += step;
        *state = 3;
    }
    else if(*state==2)
    {
        *y -= step;
        *state = 4;
    }
    else if(*state==3)
    {
        *x -= step;
        *state = 1;
    }
    else if(*state==4)
    {
        *y += step;
        *state = 2;
    }
    return 0;
}

int left(int *state, int *x, int *y, int step)
{
    if(*state==1)
    {
        *y -= step;
        *state = 4;
    }
    else if(*state==2)
    {
        *x -= step;
        *state = 1;
    }
    else if(*state==3)
    {
        *y += step;
        *state = 2;
    }
    else if(*state==4)
    {
        *x += step;
        *state = 3;
    }
    return 0;
}

int right(int *state, int *x, int *y, int step)
{
    if(*state==1)
    {
        *y += step;
        *state = 2;
    }
    else if(*state==2)
    {
        *x += step;
        *state = 3;
    }
    else if(*state==3)
    {
        *y -= step;
        *state = 4;
    }
    else if(*state==4)
    {
        *x -= step;
        *state = 1;
    }
    return 0;
}


int main()
{
    int n;
    cin>>n;
    int x=0, y=0, state=3;
    for(int i=0;i<n;i++)
    {
        string ope;
        cin>>ope;
        int step;
        cin>>step;
        if(ope[0]=='f')
            forward(&state, &x, &y, step);
        else if(ope[0]=='b')
            back(&state, &x, &y, step);
        else if(ope[0]=='l')
            left(&state, &x, &y, step);
        else
            right(&state, &x, &y, step);
    }
    cout<<x<<" "<<y;
    return 0;
}

【暴力枚举】

【基础训练-暴力枚举】Safecracker_It's the Climb-CSDN博客

  • 对于字母,要转换成数字:c-'A'+1
  • 对于输入,预先不告诉你要输入多少行,怎么写while循环来读取输入?
while(cin >> target >> s && target) {   // 输入的target不为0;有输入就会继续
        solve(target, s);  
    }  

【二进制枚举】

【蓝桥杯-二进制枚举】李白喝酒_It's the Climb-CSDN博客

主要是记住:1<<n 表示将1左移了n位,相当于在1后面加了n个0,得到是二进制数。比如1<<1,得到是10,实际值为2。

然后就通过这种枚举,按位去&,从而在有限可能性次数内枚举不同的情况。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值