【大数要在过程中取余】
【蓝桥杯-结果填空】斐波那契数列_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>
·排序
- 定义:vector<int> outputs;
- 加入:outputs.push_back(a);
- 排序:sort(outputs.begin(), outputs.end());
【大数加法】
【蓝桥杯-基础训练】A+B_It's the Climb-CSDN博客
·char数组存储大数:
- 初始化:char A[501], B[501] = {0}; // 这里初始化为0,实际ASCII码是'\0',代表字符数组的终结符
- 输入:scanf("%s%s", A, B); //采用scanf
- 计算实际长度:int len_A = strlen(A); //strlen函数判断的唯一标准是'\0'
- 字符取出来转数字:a1 = A[1] - '0';
- 直接存元素为数字类型:A[1] = 5;
- 如果直接存元素为数字类型,输出要注意明确类型:prinf("%d", A[1]); //不能直接用cout,否则输出的是实际的ASCII码而非我们要的数值!
- 如果直接存元素为数字类型,之后就不能用strlen了,因为如果有个数字0,就相当于终结符了。
·常识:两个n位数相加,结果最多为n+1位数。
【交叉排序】
主要是要了解vector<int>(容器)的用法——很方便进行排序!。
- 定义: vector<int> A;
- 入栈:A.push_back(a);
- 排序:sort(A.begin(), A.end()); 注意是前闭后开的。对其中某一段进行排序可以是sort(A.begin()+l1-1, A.begin()+r1); 同时注意默认从小到大排序。
- 打印栈顶:cout<<A.back();
- 打印栈顶后紧接一个出栈操作:A.pop_back();
- 如果是想按原有输入顺序来输出,则在步骤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> 栈(遵循先进后出):
- 定义:stack<int> S;
- 进栈:S.push(a);
- 出栈:S.pop(a);
- 打印栈顶元素: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。
然后就通过这种枚举,按位去&,从而在有限可能性次数内枚举不同的情况。