算法小记
写在前面:
这个是最近刷蓝桥杯的题时感觉需要记录的东西,感觉写在这里方便查阅。
但是自己太懒了OTZ,就想到什么就把他们堆在这里了,等有机会再整理一下吧(就是不会整理了的意思OTZ)
最近更新时间 2018/03/31
正文:
1.用什么int,直接用long long
2.递归算法
可从前往后考虑,也可从后往前考虑。(经常从后往前考虑简单得多)
3.十六进制转八进制
先将16进制转为2进制再将2进制转为8进制,1位16进制数对应4位2进制数,1位八进制数对应3位2进制数
4.十进制转十六进制 自己犯的错while(a>0) 没考虑a=0的情况
5.超不了内存的时候,用二维数组要比用两个数组互相赋值简单
6.超级好用的排序函数 sort() 时间复杂度o(nlogn)
需要 头文件#include<algorithm>和using namespace std;
用法 默认从小到大排序 a是数组首地址 a+10就是排序到第10个
int a[20]={2,3,5,1,3,4,8,5,2,1,4};
sort(a,a+10);
对自定义类型排序 这里仿照了 https://blog.csdn.net/lu597203933/article/details/41776701 (萌新不知道这么放链接合适吗。。。) 写得很详细
实现对自定义的对象类型进行排序(按照其中的元素),首先将对象存放在vector中,然后利用algorithm库函数中的sort对其进行排序,需要重写排序函数以函数名
作为函数指针作为sort的第三个参数
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
struct myclass{
int a;
int b;
};
void addmyclass(vector<myclass> &vec, int a, int b){ //方便的加入一个自定义类型对象
myclass m;
m.a = a;
m.b = b;
vec.push_back(m);
}
// 按照a排序 升序
bool com(const myclass &m1, const myclass &m2){
return m1.a < m2.a;
}
// 先按照a排 a一样 按照b排
bool comAll(const myclass &m1, const myclass &m2){
if(m1.a < m2.a) return true;
else if(m1.a > m2.a) return false;
else return m1.b < m2.b;
}
int main(){
vector<myclass> vec;
addmyclass(vec, 20, 1);
addmyclass(vec, 20, 2);
sort(vec.begin(), vec.end(), comAll);
for(vector<myclass>::iterator iter = vec.begin(); iter != vec.end(); ++iter){//vector遍历的好方法
cout << (*iter).a << " " << (*iter).b << endl;
}
}
7.C++ 中queue(队列)的用法
#include<queue>
定义一个queue的变量 queue<Type> q;
查看是否为空范例 q.empty() 是的话返回1,不是返回0;
从已有元素后面增加元素 q.push()
输出现有元素的个数 q.size()
显示第一个元素 q.front()
显示最后一个元素 q.back()
清除第一个元素 q.pop()
8.stack
c++ stl栈stack的头文件为:
#include <stack>
c++ stl栈stack的成员函数介绍
操作 比较和分配堆栈
empty() 堆栈为空则返回真
pop() 移除栈顶元素
push() 在栈顶增加元素
size() 返回栈中元素数目
top() 返回栈顶元素
9.利用vector实现图的边链表深度优先遍历 (树也可以用,树即有向图)
这是一道树形动态规划的题
问题描述
有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?
输入格式
第一行包含一个整数 n 。
接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。
接下来一共 n-1 行,每行描述树上的一条边。
输出格式
输出一个整数,代表选出的点的权值和的最大值。
样例输入
5
1 2 3 4 5
1 2
1 3
2 4
2 5
样例输出
12
#include <iostream>
#include <vector>
using namespace std;
const int MAX_N = 100005;
int v[MAX_N];//权值
int vis[MAX_N];//记录访问
int n;
vector<int>vec[MAX_N];//存边的信息
//状态转移方程为:dp[s][0]+=dp[u][1];
// dp[s][1]+=max(dp[u][0],dp[u][1]);
//(u为s的子节点,0表示包含自己的以s为根节点的子树最大值
//,1表示不包含自己的以s为根节点的子树最大值)
int dp[MAX_N][2];//状态转移方程用
void dfs(int s) //s代表从s开始向子节点判断
{
dp[s][0] = v[s];
for(int i=0; i<vec[s].size(); ++i)
{
if(vis[vec[s][i]] == 0)
{
vis[vec[s][i]] = 1;
dfs(vec[s][i]);
vis[vec[s][i]] = 0;
//---------------------
dp[s][0]+=dp[vec[s][i]][1];
dp[s][1]+=max(dp[vec[s][i]][0],dp[vec[s][i]][1]);
}
}
}
void print()//测试用函数
{
for(int i=1; i<n+1; i++)
{
cout<<"i:"<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;
}
}
int main()
{
int a,b;
cin>>n;
for(int i=1; i<n+1; i++)
{
cin>>v[i];
}
for(int i=0; i<n-1; i++) //边
{
cin>>a>>b;
vec[a].push_back(b);
vec[b].push_back(a);
}
vis[1] = 1;
dfs(1);
vis[1] = 0;
//print();
long long res = max(dp[1][0], dp[1][1]);
cout<<res;
return 0;
}
10.答题代码样式参照
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX_N = 1005;
int a[MAX_N];
int t[MAX_N];
int res[MAX_N],ri;
int n,m;
int l,r,k;
//--------------------------
/*
5
1 2 3 4 5
2
1 5 2
2 3 2
*/
//-------------------------
bool com(int a, int b){//从大到小排序
return a>b;
}
//------------------------
void solve(){
int i;
for(i=l; i<=r; i++){
t[i] = a[i];
}
sort(t+l, t+r+1, com);
res[ri-m-1] = t[l+k];
}
//------------------------
int main()
{
int i,j;
cin>>n;
for(i=0; i<n; i++){
cin>>a[i];
}
cin>>m;
ri = m;
while(m--){
cin>>l>>r>>k;
l--;r--;k--;//下标从0开始
solve();
}
for(i=0; i<ri; i++)cout<<res[i]<<endl;
return 0;
}
11.由二维数组来动态规划,由上一状态推下一状态
问题描述
如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。
求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。
由于这个数目很大,请你输出它对1000000007取模后的值。
输入格式
输入包含两个正整数,K和L。
#include <iostream>
#define MOD %1000000007
using namespace std;
const int MAX_N = 105;
long long a[MAX_N][MAX_N];
int k,l;
long long res;
bool neighbor(int a, int b){//判断a和b是否相邻 相邻为true
bool flag = false;
if(a-1 == b)flag = true;
if(b-1 == a)flag = true;
return flag;
}
void print(){//测试函数
int i,j;
cout<<endl<<"a:"<<endl;
for(i=0; i<l; i++){
for(j=0; j<k; j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int i,j,h;
cin>>k>>l;
a[0][0] = 0;//开头不能为0
for(i=1; i<k; i++){
a[0][i] = 1;//其他数字都可以用
}
for(i=1; i<l; i++){//每一位
for(j=0; j<k; j++){//每个数
for(h=0; h<k; h++){//由上一位的每个数来计算
if(!neighbor(j,h))a[i][j] = (a[i][j] + a[i-1][h]) MOD;//由上一状态推下一状态
}
}
}
for(i=0; i<k; i++){
res = (res + a[l-1][i]) MOD;
}
cout<<res;
return 0;
}
12.
上一篇: 算法小记
下一篇: 模拟退火算法学习小记