赞
踩
#include <bits/stdc++.h>
1、最大公约数
int gcd(int a,int b)
{
return b == 0? a:gcd(b,a%b);
}
2、两数之间求和公式
int Sn(int a, int b)
{
return (a+b)*(b-a+1)/2;
}
1、十进制转 n 进制 短除法 void conversion(int a,int n) { if(a <= 0) { cout << 0; return; } stack<int> aa; while(a) { aa.push(a%n); a/=n; } while(!aa.empty()) { int t = aa.top(); if(t > 9) { char c = t-10 + 'A'; cout << c; }else cout << t ; aa.pop(); } } 2、n 进制转换其他十进制 n进制的数值每个位数的数 * n ^ (根据所在的位置,小数点往左从 0 开始) 的累加和
1、int 转 string #include<sstream> void i2s(int number , string &str) { stringstream ss; ss << number; ss >> str; } ps:可以用于int、double、float 转string类型 2、string 转 int int s2i(int number,string & str) { stringstream ss ; ss << str; ss >> number; return number; }
long long fastPower(long long base,long long power)
{
long long result = 1;
while(power > 0)
{
if(power&1) result = result*base%1000;
power >>= 1;
base = base*base%1000;
}
return result;
}
int partition(int arr[],int i, int j) { while(i < j) { while(i < j && arr[i] <= arr[j]) j--; if(i < j) swap(arr[i],arr[j]); while(i < j && arr[i] <= arr[j]) i++; if(i < j) swap(arr[i],arr[j]); } return i } void quick_sort(int arr[], int low, int high) { if(low < high) { int piovt = partition(arr,low,high); quick_sort(arr,low,piovt-1); quick_sort(arr,piovt+1,high); } }
主要用于查找判断两个节点之间是否存在联系。 所以主要是两个操作:1、查找根结点。2、判断并处理 整个模板可以分为三部分:初始化、查找、处理 #include <bits/stdc++.h> int id[1000]; int size[1000]; int find(p) { while(p != id[p]) { id[p] = id[id[p]]; //路径压缩,破坏树结构 p = id[p]; } return p; } void Union(int p, int q) { int i = find(p); int j = find(q); if(i == j) return ; if(size[i] <= size[j]) { id[i] = j; size[j] += size[i]; }else { id[j] = i; size[i] += size[j]; } } int main() { for(int i = 0; i < 1000; i++) { id[i] = i; size[i] = 1; } }
兔子繁殖问题{1,1,2,3,5,8,13…}
关键点:第三年之后每年的兔子数等于前一年兔子数+前两年兔子数
最遍历的解法为:通过循环递推出每年的兔子数,使用递归时间复杂度较复杂
关于图的问题,都少不了对数据的初始化
Floyd的核心代码: 主要利用中间点 K 的改变更新图中 i 到 j 的最短路径
for(int k = 1; k <= N; k++)
for(int i = 1; i <= N; i++)
for(int j = 1; j <= N; j++)
map[i][j] = min(map[i][j],map[i][k]+map[k][j]);
可能考到的问题:最短路径、可删除边、最小环
缺点:
双循环依次更新开始源点到各源点的距离 //参数 k 为开始源点 void dijkstra(int k) { dis[k] = 0; //关键 //循环遍历 for(int i = 0; i < N; i++) { int temp = -1; //标记找到的最小值 int aaa = inf; //进行迭代松弛 for(int j = 0; j < N; j++) { if( !vis[j] && dis[j]< aaa) { aaa = dis[j]; temp = j; } } if(temp == -1) return; vis[temp] = 1; //根据找到的最短路径更新 dis for(int j = 0; j < N; j++) { if(!vis[j])//找到没有确定最短路径的结点 { //判断是否是最短路径 if(dis[j] > dis[temp] + map[temp][j]) { //更新dis dis[j] = dis[temp] + map[temp][j]; } } } } }
动态规划解题步骤
1、问题抽象化
2、建立模型
3、寻找约束条件
4、判断是否满足最优性原理
5、找大问题与小问题的递推关系式
6、填表
7、寻找解组合
01背包:从 n 个物品中选中 m 个物品放入背包中,使得背包容量不超过 w 并且价值最大(每个物品都是完整的) 核心代码: w[i] 物品重量;dp[i][j] i 物品,j重量;v[i] 价值 ;index[i] 记录最优解 找出最大价值(填表) for(int i = 1; i <= n; i++) for(int j = 1; j <= w; j++) if(j < w[i]) dp[i][j] = dp[i-1][j]; else dp[i][j] = max(dp[i-1][j],dp[i][j-w[i]] + v[i]); 最优解回溯:找出选中的物品 void findMax(int i , int j) { if(i >= 0) { if(dp[i][j] == dp[i-1][j]) { index[i] = 0; findMax(i-1,j); }else if(j - w[i] >= 0 && dp[i][j] == dp[i-1][j -w[i]] + v[i]){ index[i] = 1; findMax(i-1,j-w[i]); } } }
#include <iostream> #include <algorithm> using namespace std; const int inf = 1000; //代表无线距离,没有连接 int map[100][100]; //各边关系 //补助数组的结构体 typedef struct { int lowcost; //权值 int adjvex; //与其相邻的结点 }Element; // Prim算法 //参数1:结点个数 //参数2:根结点 void Prim(int n,int w) { int temp; //记录新加入的结点 Element El[10]; //声明一个结构体变量数组,假设最多有10个结点 //初始化根结点与各结点的关系 for(int i = 0; i < n; i++) { El[i].lowcost = map[w][i]; //与结点 i 之间的权值 El[i].adjvex = w; //与结点 i 相邻的结点 } //将根结点加入树 El[w].lowcost = 0; //权值为 0 表示已经连接不需要在判断 // Prim算法的主体部分 //将剩下的所有结点遍历加入树 for(int i = 0; i < n-1;i++) { int min = 1000; //最小的权值 temp = 100; //遍历未连接结点 的权值,找到最小权值 for(int j = 0; j < n; j++) { //如果该结点还没有加入树,并且它与已经加入树的结点之间的权值 最小 if(El[j].lowcost != 0 && El[j].lowcost < min) { min = El[j].lowcost; //更新最小权值 temp = j; //记录最小权值的结点 } } //输出最小生成树的边。 El[k].adjvex为与 k 结点连接的结点 cout << El[temp].adjvex << "------" << temp << endl; El[temp].lowcost = 0; //将 temp 结点加入树 //根据新加入的结点 temp 调整与未加入树的结点之间最小权值 for(int j = 0; j < n; j++) { if(map[temp][j] < El[j].lowcost) { El[j].lowcost = map[temp][j]; El[j].adjvex = temp; } } } } int main(int argc, char** argv) { /* 测试用例 6 9 0 1 34 0 5 19 0 2 46 1 4 12 2 3 17 2 5 25 3 5 25 3 4 38 4 5 26 */ int n ,m; int a,b,c; while(cin>>n>>m) { //对图进行初始化 for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(i == j) map[i][j] = 0; else map[i][j] = inf; //边与边的关系 for(int i = 0; i < m; i++) { cin >> a >> b >> c; map[a][b] = map[b][a] = c; } Prim(n,0); } system("pause"); return 0; }
最短路径问题:关于单源点Dijkstra与多源点Floyd 算法的区别与选择。
单源点:只记录从开始结点到各结点之间最短的路径,
通过与dfs算法的结合可以解决 最短路径 + 最小权值 + 路过的结点等问题的组合。
使用一维数组进制记录,dfs需要二维数组
多源点:使用二维数组记录各结点之间的最短路径。
最小生成树与最短路径的区别:
最短路径求的是到结点的最小距离
而最小生成树求的是整个树的权值最小
prim算法就是从根结点出发遍历出与它相连的最小权值的结点,再通过找到的结点更新。从这方面来看与Dijkstra算法很相似。
Dijkstra + dfs 的结合。
prim
typedef struct
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。