目录
1.背包问题_01背包
https://blog.csdn.net/insistgogo/article/details/8579597
2.DIjkstra算法
https://www.cnblogs.com/jason2003/p/7222182.html
单纯求起始点各点最短路径长度代码:
#include<iostream>
#include<memory.h>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int map[100][100];
bool vis[100];
int dis[100];
int n, m;
/*
测试数据
10 12
1 4 1
1 5 1
1 6 1
4 8 1
4 3 1
3 5 1
5 7 1
3 7 1
6 2 1
7 2 1
7 10 1
2 9 1
*/
void Dijkstra(int u)
{
memset(dis, INF, sizeof dis);
int start = u;
vis[start] = 1;
for (int i = 1; i <= n; ++i)
dis[i] = map[start][i];
//因为第一个结点已经标记 所以应该循环n-1次
for (int i = 1; i < n; ++i)
{
int minn = INF;
for(int j=1;j<=n;++j)
if (vis[j] == 0 && minn > dis[j])
{
//这里不是dis[start]+map[start][j]
//而应该是 minn>dis[j]
//因为我们寻找的应该是到源点最近的点
minn = dis[j];
start = j;
}
vis[start] = 1;
for (int i = 1; i <= n; ++i)
{
dis[i] = min(dis[i], dis[start]+map[start][i]);
//这里不是map[start][i]
//而是dis[start]+map[start][i]
//防止出现start结点直接到i结点的距离比绕了几个节点到i距离小的情况
}
}
}
int main()
{
int x, y, z;
cin >> n >> m;
memset(map, INF, sizeof map);//将所有路线初始化为∞ 表示无法连通
for (int i = 0; i < m; ++i)
{
cin >> x >> y >> z;
map[x][y] = map[y][x] = z;//将连通道路以及耗费代价记录
}
for (int i = 1; i <= n; ++i)//每一个结点到自身的耗费代价为0
map[i][i] = 0;
Dijkstra(1);
for (int i = 1; i <= n; ++i)
{
if (dis[i] != INF)
cout << "1->"<<i << ' ' << dis[i] << endl;
}
}
求起始节点到各个节点最短路径以及长度:
#include<iostream>
#include<memory.h>
#include<string>
#include<algorithm>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
int map[501][501];
bool vis[501];
int dis[501];
int num[501];
int n, m,s,d;
string path[501];
string init_path = "V1";
/*
测试数据
10 12
1 4 1
1 5 1
1 6 1
4 8 1
4 3 1
3 5 1
5 7 1
3 7 1
6 2 1
7 2 1
7 10 1
2 9 1
*/
void Dijkstra(int u)
{
mem(dis, INF);
int start = u;
vis[start] = 1;
for (int i = 1; i <= n; ++i)
dis[i] = map[start][i];
for (int i = 2; i <= n; ++i)
path[i] = init_path + "V" + to_string(i);
for (int i = 1; i <= n; ++i)
{
int minn = INF;
for (int j = 1; j <= n; ++j)
if (vis[j] == 0 && minn > dis[j])
{
minn = dis[j];
start = j;
}
vis[start] = 1;
for (int i = 2; i <= n; ++i)
{
if (map[start][i] != INF && vis[i] == 0)
{//如果新加入的节点ii到i节点有路径 而且i不在已选取的节点中
if (dis[i] != INF)
{//v1到i节点有路径 ???
if (dis[i] > dis[start] + map[start][i])
{//而且 经过ii节点的路径更短
dis[i] = dis[start] + map[start][i];
path[i] = path[start] + "V" + to_string(i);
}
}
else
{//v1到i没有路径
dis[i] = dis[start] + map[start][i];
path[i] = path[start] + "V" + to_string(i);
}
}
}
}
}
int main()
{
int x, y, z;
cin >> n >> m/*>>s>>d*/;
/*for (int i = 1; i <= n; ++i)
cin >> num[i];*/
mem(map, INF);
for (int i = 0; i < m; ++i)
{
cin >> x >> y >> z;
map[x][y] = map[y][x] = z;
}
for (int i = 1; i <= n; ++i)
map[i][i] = 0;
Dijkstra(1);
for (int i = 2; i <= n; ++i)
if (dis[i] != INF)
cout << path[i] <<" "<<dis[i]<< endl;
}
代码效果:
3.KMP算法
#include<iostream>
#include<cstring>
using namespace std;
void prefix_table(char pattern[], int prefix[], int len)
{
prefix[0] = 0;
int i = 0, j = 1;
while (j < len)
{
if (pattern[i] == pattern[j])
prefix[j++] = ++i;
else
{
if (i > 0)
i = prefix[i - 1];
else
prefix[j++] = 0;
}
}
}
void move_prefix_table(int prefix[], int len)
{
for (int i = len - 1; i > 0; --i)
prefix[i] = prefix[i - 1];
prefix[0] = -1;
}
void KMP_search(char text[], char pattern[])
{
int n = strlen(pattern);
int m = strlen(text);
int i = 0, j = 0;
int *prefix = new int[n];
prefix_table(pattern, prefix, n);
move_prefix_table(prefix, n);
// text[i] , strlen(text) = n
//pattern[j] , strlen(pattern) = m
while (i < m)
{
if (text[i] == pattern[j])
{
if (j == n - 1)
{
printf("Found at %d\n", i-j);
j = prefix[j];
}
i++, j++;
}
else
{
j = prefix[j];
if (j == -1)
i++, j++;
}
}
}
int main()
{
char text[50], pattern[50];
cin >> text >> pattern;
KMP_search(text, pattern);
}
测试结果:
4.并查集算法(查找图中是否存在环)
#include<iostream>
#include<cstring>
using namespace std;
#define VERTICES 6
void initialise(int parent[])
{
for (int i = 0; i < VERTICES; ++i)
parent[i] = i;
}
int find_root(int x, int parent[])
{
int x_root = x;
while (parent[x_root] !=x_root)
x_root = parent[x_root];
return x_root;
}
int union_vertices(int x,int y,int parent[])
{
int x_root = find_root(x, parent);
int y_root = find_root(y, parent);
if (x_root == y_root)
{
printf("%d and %d has root %d\n", x,y,x_root);
return 0;
}
else
{
parent[x_root] = y_root;
return 1;
}
}
int main()
{
int parent[VERTICES] = { 0 };
int edges[5][2]=
{
{1,3},{1,2},{2,5},{3,4},{4,5}
};
initialise(parent);
for (int i = 0; i < 5; ++i)
{
if (union_vertices(edges[i][0], edges[i][1], parent) == 0)
{
printf("Cycle Found\n");
break;
}
}
printf("No Cycle Found\n");
return 0;
}
更加高效的并查集查找:
string& find(string &t) {
if (dp.find(t) == dp.end())
return t;
string st = dp[t];
if (st == t) return t;
else return dp[t] = find(st);
}
void merge(string &a, string &b)
{
string aa = find(a);
string bb = find(b);
if (aa != bb)
dp[aa] = bb;
}
我也不知道为什么这样就高效了。。。有一道题这样做不会超时,我换个方式压缩路径不调用递归反而算的比这个吊用递归还慢,我毫无头绪。
5.C++中实现类似python中字典的功能
#include<iostream>
#include<vector>
#include<map>
using namespace std;
map<char, map<char,int>>dp;
int main()
{
char A, B;
int dist;
while (cin >> A >> B >> dist)
{
dp[A][B] = dist;
}
map<char, map<char, int>>::iterator it = dp.begin();
while (it != dp.end())
{
map<char, int>::iterator ite=it->second.begin();
while (ite != it->second.end())
{
cout << it->first << " -> " << ite->first << " " << ite->second << endl;
ite++;
}
it++;
}
}
代码效果:
以这个图为例:
非递归式的深度搜索与广度搜索(二者极其相似):
6.DFS:
int DFS(int x,int y)
{
stack<Type>sta;
sta.push(Type(x,y));
while(!sta.empty())
{
Type t=sta.top();
sta.pop();
for(int i=0;i<4;++i)
{
int xx=t.x+dir[i][0];
int yy=t.y+dir[i][1];
if(/*满足某种条件*/)
{
sta.push(Type(xx,yy));
//添加你要进行的额外操作
}
}
}
return 0;
}
7.BFS:
int BFS(int x,int y)
{
queue<Type>que;//修改此处
que.push(Type(x,y));
while(!que.empty())
{
Type t=que.front();//sta.top()改为que.front()
que.pop();
for(int i=0;i<4;++i)
{
int xx=t.x+dir[i][0];
int yy=t.y+dir[i][1];
if(/*满足某种条件*/)
{
que.push(Type(xx,yy));
//添加你要进行的额外操作
}
}
}
return 0;
}
8.线段树:
#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
#include<queue>
#include<memory.h>
#define INF 0x3f3f3f3f
using namespace std;
void build_tree(int arr[], int tree[], int node, int start, int end)
{
if (start == end)
tree[node] = arr[start];
else
{
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
build_tree(arr, tree, left_node, start, mid);
build_tree(arr, tree, right_node, mid + 1, end);
tree[node] = tree[left_node] + tree[right_node];
}
}
void update(int arr[], int tree[], int node, int start, int end, int idx, int val)
{
if (start == end)
{
arr[idx] = val;
tree[node] = val;
}
else
{
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
if(idx<=mid)
update(arr, tree, left_node, start, mid, idx, val);
else
update(arr, tree, right_node,mid+1, end, idx, val);
tree[node] = tree[left_node] + tree[right_node];
}
}
int query_tree(int arr[], int tree[], int node, int start, int end, int L, int R)
{
if (L > end || R < start)
return 0;
if (L<=start&&end<=R)
return tree[node];
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
int sum_left = query_tree(arr, tree, left_node, start, mid, L, R);
int sum_right = query_tree(arr, tree, right_node, mid + 1, end, L, R);
return sum_left + sum_right;
}
int main()
{
int arr[] = { 1,3,5,7,9,11 };
int size = 6;
int tree[100] = { 0 };
build_tree(arr, tree, 0, 0, size - 1);
update(arr, tree, 0, 0, size - 1,4,6);
for (int i = 0; i < 15; ++i)
printf("tree[%d] = %d\n",i, tree[i]);
cout << query_tree(arr, tree, 0, 0, size - 1, 2, 5);
}