【笔记】一些算法模板(C++)


1、BFS(广搜)模板题

涂色问题——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
int dian, bian;
vector <vector<int> > v;
int colour[maxn];
bool bfs() {
	queue<int> que;
	que.push(0);
	colour[0] = 1;
	while(que.size()) {
		int a = que.front();
		que.pop();
		for(int i = 0; i < v[a].size(); i++) {
			int j = v[a][i];
			if(colour[j] == colour[a]) return false;
			if(colour[j] == 0) {
				colour[j] = colour[a] * -1;
				que.push(j);
			}
		}
	}
	return true;
}
int main() {
	while(cin >> dian >> bian && dian) {
		v.clear();
		v.resize(dian, vector<int>() );
		fill(colour, colour + maxn, 0);
		for(int i = 0; i < bian; i++) {
			int x, y;
			cin >> x >> y;
			v[x].push_back(y);
			v[y].push_back(x);
		}
		if(bfs()) cout << "BICOLORABLE." << endl;
		else cout << "NOT BICOLORABLE." << endl;
	}
	return 0;
}

蓝桥杯国赛,扩散——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 10000;
long long ans;
int a[N][N], hy[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
struct node{
	int x, y, st;
}s, t;
void bfs(){
	int i;
	queue<node> q;
	q.push((node){0 + 2100, 0 + 2100, 0});
	q.push((node){2020 + 2100, 11 + 2100, 0});
	q.push((node){11 + 2100, 14 + 2100, 0});
	q.push((node){2000 + 2100, 2000 + 2100, 0});
	a[0 + 2100][0 + 2100] = a[2020 + 2100][11 + 2100] = a[11 + 2100][14 + 2100] = a[2000 + 2100][2000 + 2100] = 1;
	ans = 4;
	while(q.size()){
		t = q.front();
		q.pop();
		s.st = t.st + 1;
		for(int i = 0; i < 4; i++){
			s.x = t.x + hy[i][0];
			s.y = t.y + hy[i][1];
			if(a[s.x][s.y] == 0 && s.st <= 2020){
				a[s.x][s.y] = 1;
				ans++;
				q.push(s);
			}
		}
	}
	cout << ans;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	bfs();
	return 0;
	
} 

2、DFS(深搜)模板题

油井问题——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1007;
int m, n, dx, dy, ans;
char map1[maxn][maxn];
int xx[8] = {1, 1, 1, 0, -1, -1, -1 , 0}, yy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
void dfs(int x, int y) {
	map1[x][y] = '*';
	for(int i = 0; i < 8; i++) {
		dx = x + xx[i];
		dy = y + yy[i];
		if(dx >= 1 && dx <= m && dy >= 1 && dy <= n && map1[dx][dy] == '@') dfs(dx, dy);
	}
	return ;
}
void solve() {
	ans = 0;
	for(int i = 1; i <= m; i++)
		for(int j = 1; j <= n; j++)
			if(map1[i][j] == '@') {
				dfs(i, j);
				ans++;
			}
}
int main() {
	while(cin >> m >> n && m && n) {
		for(int i = 1; i <= m; i++)
			for(int j = 1; j <= n; j++)
				cin >> map1[i][j];
		solve();
		cout << ans << endl;
	}
	return 0;
}

3、Dijstra(单源最短路径)模板题

优先队列优化——代码如下:

#include<bits/stdc++.h>
#include<functional>
using namespace std;
typedef pair<int, int> P;
vector<vector<P > > v;
int n, m, s, d;
int cnt[505], dis[505], last[505], curSum[505], path[505];
bool vis[505];
void dijkstra() {
	for(int i = 0; i < 505; i++) {
		dis[i] = INT_MAX >> 1;
		vis[i] = false;
		last[i] = -1;
		curSum[i] = cnt[i];
		path[i] = 1;
	}
	dis[s] = 0;
	priority_queue<P, vector<P>, greater<P> > q;
	q.push(make_pair(0, s));
	while(q.size()) {
		P e = q.top();
		q.pop();
		int z = e.first, y = e.second;
		if(vis[y] == true) continue;
		vis[y] = true;
		for(int i = 0; i < v[y].size(); i++) {
			int x = v[y][i].second, z = v[y][i].first;
			if(dis[y] + z < dis[x]) {
				curSum[x] = curSum[y] + cnt[x];
				dis[x] = dis[y] + z;
				last[x] = y;
				q.push(make_pair(dis[x], x));
				path[x] = path[y];
			} else if(dis[x] == dis[y] + z) {
				path[x] = path[x] + path[y];
				if(curSum[x] < curSum[y] + cnt[x]) {
					curSum[x] = curSum[y] + cnt[x];
					last[x] = y;
					q.push(make_pair(dis[x], x));
				}
			}
		}
	}
}
int main() {
	cin >> n >> m >> s >> d;
	for(int i = 0; i < n; i++) cin >> cnt[i];
	v.resize(n);
	for(int i = 0; i < m; i++) {
		int x, y, z;
		cin >> x >> y >> z;
		v[x].push_back(make_pair(z, y));
		v[y].push_back(make_pair(z, x));
	}
	dijkstra();
	cout << path[d] << " " << curSum[d] << endl;
	vector<int > ans;
	int g = d;
	while(g != -1) {
		ans.push_back(g);
		g = last[g];
	}
	for(int i = ans.size() - 1; i >= 0; i--) {
		if(i < ans.size() - 1) cout << " ";
		cout << ans[i];
	}
	return 0;
}

朴素算法——代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1007;
const int inf = 1<<30;
int n, m, s, g[maxn][maxn];//n点数,m边数,s起始位置
int d[maxn];
bool vis[maxn] = {false};
void dijsktra() {
	s = 1;
	fill(d, d + maxn, inf);
	d[s] = 0;
	for(int i = 0; i < n; i++) {
		int u = -1, min = inf;
		for(int j = 1; j <= n; j++) {
			if(vis[j] == false && d[j] < min) {
				u = j;
				min = d[j];
			}
		}
		if(u == -1) continue;
		vis[u] = true;
		for(int v = 1; v <= n; v++) {
			if(vis[v] == false && g[u][v] != inf && d[u] + g[u][v] < d[v]) {
				d[v] = d[u] + g[u][v];
			}
		}
	}
}
int main() {
	int u, v, w;
	cin >> m >> n;
	fill(g[0], g[0] + maxn * maxn, inf);
	for(int i = 0; i < m; i++) {
		cin >> u >> v >> w;
		g[u][v] = g[v][u] = min(g[u][v],w);
	}
	dijsktra();
	cout << d[n] << endl;
	return 0;
}

天梯赛,网红景点——代码如下:

#include<bits/stdc++.h>
using namespace std;
int mp[205][205], vis[205];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	for(int i = 0; i < m; i++){
		int x, y, z;
		cin >> x >> y >> z;
		mp[x][y] = mp[y][x] = z;
	}
	int k, l, cnt = 0, no, ans = 1e9 + 2;
	cin >> k;
	for(int i = 1; i <= k; i++){
		cin >> l;
		int f = 0, sum = 0, last = 0, ct = 0;
		fill(vis, vis + 205, 0);
		for(int j = 0; j < l; j++){
			int t;
			cin >> t;
			if(vis[t] == 1) f = 1;
			vis[t] = 1;
			if(mp[last][t] == 0) f = 1;
			sum += mp[last][t];
			last = t;
			ct++;
		}
		if(mp[last][0] == 0) f = 1;
		if(ct != n) f = 1;
		if(f == 1) continue;
		cnt++;
		sum += mp[last][0];
		if(sum < ans){
			ans = sum;
			no = i;
		}
	}
	cout << cnt << endl << no << " " << ans;
	return 0;
} 

天梯赛练习L3-直捣黄龙——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int Inf = 9999999;
const int o = 205;

int graph[o][o];
bool vis[o];//标记路径
int dist[o];//存最短路径
int path[o];//存路径
int kill[o];//存杀敌数
int node[o];//存经过的城市数量
int army[o];//各城市的士兵
int road[o];//最短路径的数量
int n;
map<string, int> M;
map<int, string> N;
void Dijkstra(int sta, int end) {
	memset(vis, 0, sizeof(vis));
	memset(dist, Inf, sizeof(dist));
	memset(path, -1, sizeof(path));
	memset(kill, 0, sizeof(kill));
	memset(node, 0, sizeof(node));
	memset(road, 0, sizeof(road));
	vis[sta] = true;
	dist[sta] = 0;
	for(int i = 0; i < n; i++) {
		if(!vis[i] && graph[sta][i]) {
			dist[i] = graph[sta][i];
			node[i] = 1;
			kill[i] = army[i];
			path[i] = sta;
			road[i] = 1;
		}
	}
	while(1) {
		int minn = Inf, v = sta;
		for(int i = 0; i < n; i++) {
			if(!vis[i] && dist[i] < minn) {
				minn = dist[i];
				v = i;
			}
		}
		if(v == end) break;
		vis[v] = true;
		for(int i = 0; i < n; i++) {
			if(!vis[i] && graph[v][i] + minn <= dist[i]) {
				if(graph[v][i] + minn < dist[i]) {
					dist[i] = graph[v][i] + minn;
					node[i] = node[v] + 1; 
					kill[i] = kill[v] + army[i];
					path[i] = v;
					road[i] = road[v];
				} else {
					road[i] += road[v];
					if(node[v] + 1 >= node[i]) {
						if(node[v] + 1 > node[i]) {
							kill[i] = kill[v] + army[i];
							node[i] = node[v] + 1;
							path[i] = v;
						} else {
							if(kill[v] + army[i] > kill[i]) {
								kill[i] = kill[v] + army[i];
								path[i] = v;
							}
						}
					}
				}
			}
		}
	}
}
void find(int x) {
	if(path[x] != -1) {
		find(path[x]);
		cout << N[path[x]] << "->";
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int i, m;
	string s, e;
	cin >> n >> m >> s >> e;
	M[s] = 0;
	N[0] = s;
	army[0] = 0;
	string str;
	for(int i = 1; i < n; i++) {
		cin >> str >> army[i];
		M[str] = i;
		N[i] = str;
	}
	string x, y;
	int w;
	memset(graph, Inf, sizeof(graph));
	for(int i = 0; i < m; i++) {
		cin >> x >> y >> w;
		graph[M[x]][M[y]] = w;
		graph[M[y]][M[x]] = w;
	}
	Dijkstra(M[s], M[e]);
	find(M[e]);
	cout << e << endl;
	printf("%d %d %d", road[M[e]], dist[M[e]], kill[M[e]]);
	return 0;
}

4、Floyd(多源最短路径)模板题

3for算法,带记录路径——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int inf = 1<<29;
int num[505], dis[505][505], res[505][505];
int N, M, S, D, ans;
int floy(){
	for(int k = 0; k < N; k++){
		for(int i = 0; i < N; i++){
			for(int j = 0; j < N; j++){
				if(dis[i][k] != inf && dis[k][j] != inf && dis[i][k] + dis[k][j] <= dis[i][j] && num[i] + num[k] + num[j] > num[i] + num[j]){
					dis[i][j] = dis[i][k] + dis[k][j];
					res[i][j] = res[i][k];
				}
			}
		}
	}
	return 0;
}
int main(){
	fill(dis[0], dis[0] + 505 * 505, inf);
	cin >> N >> M >> S >> D;
	for(int i = 0; i < N; i++) cin >> num[i];
	for(int i = 0; i < M; i++){
		int x, y, z;
		cin >> x >> y >> z;
		dis[x][y] = dis[y][x] = z;
		res[x][y] = y;
		res[y][x] = x;
	}
	floy();
	int f = S, g = D, cnt = 0;
	ans = num[g];
	while(f != g){
		ans = ans + num[f];
		cnt++;
		if(g == res[f][g]) break;
		f = res[f][g];
	}
	cout << cnt << " " << ans << endl;
	f = S, g = D;
	cout << f;
	while(f != g){
		cout << " " << res[f][g];
		if(g == res[f][g]) break;
		f = res[f][g];
	}
	return 0;
}

5、链表操作

链表去重——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
struct Node {
	int address;
	int data;
	int next;
	int num = maxn * 2;
} node[maxn];
bool vis[maxn];
bool cmp(Node a, Node b) {
	return a.num < b.num;
}
int main() {
	int head, n, x, c, c1 = 0, c2 = 0;
	cin >> head >> n;
	for(int i = 0; i < n; i++) {
		cin >> x;
		cin >> node[x].data >> node[x].next;
		node[x].address = x;
	}
	for(int i = head; i != -1; i = node[i].next) {
		if(!vis[abs(node[i].data)]) {
			vis[abs(node[i].data)] = true;
			node[i].num = c1++;
		}
		else node[i].num = maxn + c2++;
	}
	sort(node, node + maxn, cmp);
	c = c1 + c2;
	for(int i = 0; i < c; i++) {
		if(i != c1 - 1 && i != c - 1) printf("%05d %d %05d\n", node[i].address, node[i].data, node[i + 1].address);
		else printf("%05d %d -1\n", node[i].address, node[i].data);
	}
	return 0;
}

反转链表——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int main(){
	int first, n, k, temp;
	int next[maxn], data[maxn], list[maxn];
	cin >> first >> n >> k;
	for(int i = 0; i < n; i++){
		cin >> temp;
		cin >> data[temp] >> next[temp];
	}
	int sum = 0;
	while(first != -1){
		list[sum++] = first;
		first = next[first];
	}
	for(int i = 0; i < sum - (sum % k); i += k){
		reverse(begin(list) + i, begin(list) + i + k);
	}
	for(int i = 0; i < sum - 1; i++){
		printf("%05d %d %05d\n", list[i], data[list[i]], list[i+1]);
	}
	printf("%05d %d -1", list[sum - 1], data[list[sum - 1]]);
	return 0;
} 

6、栈的运用

取栈的top时需要判断栈是否为空,不然会报错!

出栈顺序合法性——代码如下:

#include<bits/stdc++.h>
using namespace std;
stack<int> s;
queue<int> q;
int main(){
    int m, n, k;
    cin >> m >> n >> k;
    while(k--){
        while(!s.empty()) s.pop();
        while(!q.empty()) q.pop();
        for(int i = 0; i < n; i++){
            int x;
            cin >> x;
            q.push(x);
        }
        int num = 1;
        while(!q.empty() && s.size() < m){
            s.push(num);
            num++;
            while(!s.empty() && !q.empty() && s.top() == q.front()){
                s.pop();
                q.pop();
            }
            if(num == n + 1) break;
        }
        if(num == n + 1 && s.empty()) cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}

7、树

二叉搜索树

二叉搜索树建树和结点统计——代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int l[N], r[N], w[N], id, cnt[N], ma;
//l,r为左右儿子,w是结点权值,cnt记录每层的结点数,ma是最深深度
void build(int &x, int ww) {//建立二叉搜索树
	if(!x) {
		x = ++id;
		w[x] = ww;
	} else {
		if(ww <= w[x]) build(l[x], ww);
		else build(r[x], ww);
	}
}
void dfs(int x, int depth) {
	if(!x) return;
	cnt[depth]++;
	ma = max(ma, depth);//ma为最深深度
	dfs(l[x], depth + 1);
	dfs(r[x], depth + 1);
}
int main() {
	int n, rt = 0;
	cin >> n;
	for(int i = 0; i < n; i++) {
		int xx;
		cin >> xx;
		build(rt, xx);
	}
	dfs(rt, 0);
	cout << cnt[ma] + cnt[ma - 1] << endl;
	return 0;
}

完全二叉树的三种遍历

前序,中序,后序——代码如下:

//完全二叉树的三种遍历建树 
#include<bits/stdc++.h>
using namespace std;
int a[1000], tree[1000];
int n, cnt;
void dfs(int u){
	if(u > n) return;
	int lson = 2 * u;
	int rson = 2 * u + 1;
	/*前序遍历建树 (从顶开始,先所有左边,然后再右) 
	tree[u] = a[++cnt];
	dfs(lson);
	dfs(rson);
	*/
	 /*中序遍历建树 (从最左开始,左中右) 
	dfs(lson);
	tree[u] = a[++cnt];
	dfs(rson);
	*/
	 /*前序遍历建树 (从最左开始,左右中) 
	dfs(lson);
	dfs(rson);
	tree[u] = a[++cnt];
	*/
}
int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	dfs(1);
	//按照层序遍历输出 
	for(int i = 1; i <= n; i++) printf("%d ", tree[i]);
	return 0;
} 

8、并查集

并查集就是最左最大和最右最大两种形式找大哥,每个集团只有一个大哥,大哥的编号就是本人,小弟的编号都为集团的大哥的编号,最后看有多少个大哥就是有多少集团。

天梯赛,部落——代码如下:

#include<bits/stdc++.h>
using namespace std;
int m, x, y, sum, n, cnt, k, f[10005], a[10005], b[10005];
int num;
int boss(int x) {
	if(f[x] == x) return x;
	else {
        f[x] = boss(f[x]);
        return(boss(f[x]));
    } 
}
int main() {
	cin >> n;
	for(int i = 0; i < n; i++) {
		cin >> k;
		for(int j = 0; j < k; j++) {
			cin >> a[j];
			if(f[a[j]] == 0) {
				f[a[j]] = a[j];
				b[cnt++] = a[j];
			}
		}
		for(int j = 1; j < k; j++){
            f[boss(a[j])] = boss(a[0]);
            num++;
        }
	}
	cout << cnt << " " << cnt - num << endl;
	cin >> m;
	for(int i = 0; i < m; i++) {
		cin >> x >> y;
		if(boss(x) != boss(y)) cout << "N\n";
		else cout << "Y\n";
	}
	return 0;
}

总结

对于算法模板熟练套用才能加快做题的节奏。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是BFS和DFS算法C++模板BFS算法模板: ```cpp #include <iostream> #include <queue> using namespace std; void BFS(int start, int end) { queue<int> q; bool visited[n]; // 标记节点是否被访问过 int level[n]; // 记录节点的层级 // 初始化visited和level数组 for (int i = 0; i < n; i++) { visited[i = false; level[i = 0; } q.push(start); visited[start = true; while (!q.empty()) { int current = q.front(); q.pop(); // 进行当前节点的操作 for (int neighbor : 获取当前节点的所有邻居节点) { if (!visited = true; level = level[current + 1; } } } // 输出结果,例如输出最短路径的长度 cout << "最短路径长度为:" << level[end << endl; } ``` DFS算法模板: ```cpp #include <iostream> using namespace std; void DFS(int current, bool visited[]) { // 进行当前节点的操作 visited[current = true; // 标记当前节点已访问 for (int neighbor : 获取当前节点的所有邻居节点) { if (!visited = false; } DFS(start, visited); return 0; } ``` 这些模板可以用于解决各种问题,如迷宫、八皇后、n皇后、油田、连通块、数独等。在使用时,根据具体问题的要求选择适合的算法,并按照注释部分进行相应的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [DFS和BFS理解+模板+例题](https://blog.csdn.net/weixin_43876357/article/details/112552683)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Why_so?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值