学校算法实验课代码

学校算法实验课代码

如有补充请联系我

选择排序

void select_sort(int *a, int n) {
	for (int i = 0; i < n; i++) {
		int t = i;
		for (int j = i + 1; j < n; j++) {
			if (a[j] < a[t]) t = j;
		}
		if (i != t) swap(a[t], a[i]);
	}
}

插入排序

void insert_sort(int *a, int n) {
	for (int i = 1; i < n; i++) {
		int t = a[i];
		int j = i;
		while (j > 0 && t < a[j - 1]) {
			a[j] = a[j - 1];
			j--;
		}
		a[j] = t;
	}
}

归并排序

void merge_sort(int *a, int l, int r) {
	if (r - l <= 1) {
		if (r - l == 1 && a[r] < a[l]) {
			swap(a[r], a[l]);
		}
		return ;
	}
	int mid = (l + r) >> 1;
	merge_sort(a, l, mid);
	merge_sort(a, mid + 1, r);
	
	int *temp = (int *)malloc(sizeof(int) * (r - l + 1));
	int p1 = l, p2 = mid + 1, k = 0;
	while (p1 <= mid || p2 <= r) {
		if (p2 > r || p1 <= mid && a[p1] < a[p2]) {
			temp[k++] = a[p1++];
		} else {
			temp[k++] = a[p2++];
		}
	}
	memcpy(a + l, temp, sizeof(int) * (r - l + 1));
	free(temp);
} 

逆序对

#define swap(a, b) {\
	a ^= b, b ^= a, a ^= b;\
}

void merge_sort(int *arr, int l, int r) {
	if (r - l <= 1) {
		if (r - l == 1 && arr[r] < arr[l]) {
			swap(arr[l], arr[r]);
			cnt++;
		}
		return ;
	}
	int mid = (l + r) >> 1;
	merge_sort(arr, l, mid);
	merge_sort(arr, mid + 1, r);
	
	int *temp = (int *)malloc(sizeof(int) * (r - l) + 1);
	int p1 = l, p2 = mid + 1, k = 0;
	while (p1 <= mid || p2 <= r) {
		if (p2 > r || p1 <= mid && arr[p1] <= arr[p2]) {
			temp[k++] = arr[p1++];
		} else {
			temp[k++] = arr[p2++];
			cnt += mid - p1 + 1;
		}
	}
	memcpy(arr + l, temp, sizeof(int) * (r - l + 1));
	free(temp);
}

快速排序

void quick_sort(int *q, int l, int r) {
    if (l >= r) return ;
    int i = l - 1, j = r + 1, x = q[(l + r + 1) >> 1];
    
    while (i < j) {
        do i++; while(q[i] < x);
        do j--; while(q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    
    quick_sort(q, l, i - 1), quick_sort(q, i, r);
}

快速排序求第k大值

int quick_sort(int q[], int l, int r, int k) {
    if (l >= r) return q[l];

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j) {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }

    if (j - l + 1 >= k) return quick_sort(q, l, j, k);
    else return quick_sort(q, j + 1, r, k - (j - l + 1));
}

最大子数组

#include <iostream>
using namespace std;


const int N = 100;
int a[N], dp[N], rec[N];
int n;

// 1 -2 4 5 -2 8 3 -2 6 3 7 -1 (12)
// dp[i];以a[i]结尾的最大子数组 
void max_sequence() {
	int ans = -0x3f;
	int ind;
	for (int i = 0; i < n; i++) {
		dp[i] = a[i];
		if (i > 0 && dp[i-1] > 0) {
			dp[i] += dp[i-1];
			rec[i] = rec[i-1];
		} else {
			rec[i] = i;
		}
		if (dp[i] > ans) {
			ind = i;
			ans = dp[i];
		}
	}
	cout << "最大子数组大小:" << ans << endl;
	cout << "最大子数组(l和r):" << rec[ind] << ' ' << ind << " (下标从0开始)" << endl;
}

int main() {
	cout << "数组长度及其序列:" << endl;
	cin >> n;
	for (int i = 0; i < n; i++) cin >> a[i];
	
	max_sequence();
	
	return 0;
}

最长公共子序列

#include <iostream>
#include <vector>

using namespace std;
const int N = 100;
char s1[N], s2[N];
int c[N][N];
int n, m;
string rec2[N][N];
vector<char> res;
// 7 6
// abcbdab, bdcaba
void LCS() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (s1[i] != s2[j]) {
				if (c[i][j-1] >= c[i-1][j]) {
					c[i][j] = c[i][j-1];
					rec2[i][j] = "L";
				} else {
					c[i][j] = c[i-1][j];
					rec2[i][j] = "U"; 
				}
			} else {
				c[i][j] = c[i-1][j-1] + 1;
				rec2[i][j] = "LU";
			}
		}
	}
	cout << "最长公共子序列长度: " << c[n][m] << endl; 
	
	while (c[n][m] != 0) {
		if (rec2[n][m] == "U") n--;
		else if (rec2[n][m] == "L") m--;
		else {
			res.push_back(s1[n]);
			n--, m--;
		}
	}
	for (auto x : res) {
		cout << x << ' ';
	} 
	cout << endl;
}
int main() {
	cout << "输入两个子序列:" << endl;
	cin >> n >> m;
	scanf("%s%s", s1+1, s2+1);

	LCS();
	
	return 0;
}

最长公共子串

#include <iostream>
using namespace std;

const int N = 10010;
int n, m;
char a[N], b[N];
int c[N][N], len, pos;

void print() {
	if (len == 0) {
		printf("不存在LCS\n");
		return ;
	}
	printf("LCS长度:%d\nLCS:", len);
	int i = pos - len + 1;
	while (i <= pos) putchar(a[i++]);
	puts("");
} 

void solve(char *a, char *b, int n, int m) {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (a[i] == b[j]) {
				c[i][j] = c[i-1][j-1] + 1;
				if (c[i][j] > len) {
					len = c[i][j];
					pos = i;
				}
			}
		}
	}
	print();
}
/* 
7 6
ABCADBB
BCEDBB
*/ 

int main() {
	cin >> n >> m;
	scanf("%s", a+1);
	scanf("%s", b+1);
	solve(a, b, n, m);
	return 0;
}

01背包

#include <iostream>
using namespace std;

const int N = 10010;
int f[N][N];
int rec[N][N];
int n, m;
int v[N], w[N];
/* 
输入: 
5 13
10 24 
3 2 
4 9 
5 10 
4 9  
*/
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> v[i] >> w[i];
	}
	// 未优化版本 
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			f[i][j] = f[i-1][j];
			if (j >= v[i]) {
				int t = f[i-1][j - v[i]] + w[i];
				if (t > f[i][j]) {
					f[i][j] = t;
					rec[i][j] = 1;
				}
			}
		}
	}
	cout << "最大价值为: " << f[n][m] << endl;
	cout << "所选方案: ";
	
	while (rec[n][m] != 0) {
		cout << n << ' ';
		m -= v[n];
		n -= 1;
	} 
	
	cout << endl;
	return 0;
} 

部分背包

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 10010;

/*
5 800
600 60
250 10
200 36
100 16
300 45
*/

struct goods {
	int v, w, i;
	bool operator<(const goods &b) const {
		return w / v > b.w / b.v;
	}
} g[N];

int n, v;
int rec[N];

int main() {
	cin >> n >> v;
	for (int i = 1; i <= n; i++) {
		cin >> g[i].v >> g[i].w;
		g[i].i = i;
	} 
	
	sort(g+1, g+1+n);
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		if (v > g[i].v) {
			v -= g[i].v;
			ans += g[i].w;
			rec[i] = g[i].v;
		} else {
			ans += v * g[i].w / g[i].v;
			rec[i] = v;
			break;
		}
	}

	printf("最大价值为: %d\n", ans);

	for (int i = 1; i <= n; i++) {
		if (rec[i]) {
			printf("选择%d(排序后位置为: %d)%d体积\n", g[i].i, i, rec[i]);
		}
	}
	puts("");

	return 0;
}

不带权活动选择问题(贪心)

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

struct seg {
	int i, l, r;
	bool operator<(const seg &b) const {
		return r < b.r;
	}
} s[N];

int n;
int rec[N];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i].l >> s[i].r;
		s[i].i = i;
	}

	sort(s+1, s+n+1);

	int r = s[1].r;
	int cnt = 1;
	for (int i = 2; i <= n; i++) {
		if (s[i].l < r) continue;
		cnt++;
		r = s[i].r;
		rec[i] = 1;
	}

	printf("选择的数量为:%d\n", cnt);

	// 追踪
	printf("排%d原%d (s:%d e%d)\n", 1, s[1].i, s[1].l, s[1].r);
	for (int i = 1; i <= n; i++) {
		if (rec[i]) printf("排%d原%d (s:%d e%d)\n", i, s[i].i, s[i].l, s[i].r);
	}


	return 0;
}
/*
11
1 4
3 5
0 6
5 7
3 9
5 9
6 10
8 11
8 12
2 14
12 16
*/

带权活动选择问题 (dp + 贪心 + 二分)

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 10010;

// 崔剑烁 20201836080 计科H20.1

struct seg {
	int idx, l, r, w;

	bool operator<(const seg &b) const {
		return r < b.r;
	}
} s[N];

int rec[N]; // 追踪数组
int p[N]; // 上一个可以选择的活动区间
int n;
int f[N];

bool p_check(int cur, int mid) {
	if (s[mid].r > s[cur].l) return false;
	return true;
}

// 二分查找,取得前面最近可以选择的活动区间,记录为p[i].
// 二分答案:小于等于当前l的第一个r
void get_last() {
	for (int i = 1; i <= n; i++) {
		int l = 1, r = i;

		while (l < r) {
			int mid = (l + r + 1) >> 1; // l = mid
			if (p_check(i, mid)) l = mid;
			else r = mid - 1;
		}
		p[i] = l;
	}
	p[1] = 0;
}


int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i].l >> s[i].r >> s[i].w;
		s[i].idx = i;
	}

	sort(s+1, s+1+n);

	get_last(); // 获取上一个可以选择的活动区间 p[i]

	for (int i = 1; i <= n; i++) {
		f[i] = f[i-1];
		if (f[p[i]] + s[i].w > f[i]) {
			f[i] = f[p[i]] + s[i].w;
			rec[i] = 1;
		}
	}

	// p[i]
	printf("p数组\n");
	for (int i = 1; i <= n; i++) {
		cout << p[i] << ' ';
	}
	cout << endl;

	// f[n] 为最大收益
	printf("最大收益为: %d\n", f[n]);


	// 通过rec数组追踪
	int cur = n;

	while (cur > 0) {
		if (rec[cur] == 1) {
			printf("排序序列位置:%d(原序列位置:%d), s:%d, e:%d\n", cur, s[cur].idx, s[cur].l, s[cur].r);
			cur = p[cur];
		} else {
			cur -= 1;
		}
	}

	return 0;
}

/*
10
1 4 1
3 5 6
0 6 4
4 7 7
3 9 3
5 9 12
6 10 2
8 11 9
8 12 11
2 14 8
*/

/*
5
7 9 9
7 8 1
6 7 9
6 8 5
4 9 9

5
4 7 9
3 4 4
7 8 8
8 9 6
4 5 9
*/

钢条切割 RCP

#include <iostream>
using namespace std;

const int N = 10010, M = 10010;
int len;
int n;
int p[N];
int c[M];
int rec[N];
/*
10 
1 5 8 9 10 17 17 20 24 24
*/

void print() {
	printf("RCP最大收益:%d\n方案:", c[n]);
	while(rec[n] > 0) {
		printf("%d ", rec[n]);
		n = n - rec[n];
	} 
	puts("");
}

void solve() {
	for (int i = 1; i <= n; i++) {
		c[i] = p[i];
		for (int j = 1; j < i; j++) {
			if (c[i-j] + p[j] > c[i]) {
				rec[i] = j;
				c[i] = c[i-j] + p[j];
			}
		}
	}
	print();
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> p[i];
	solve();
	
	
	return 0;
} 

矩阵链乘法 MCO

#include <iostream>
using namespace std;

const int N = 1010;

int n;

int m[N][N];
int rec[N][N];
int p[N];

void print(int l, int r) {
	if (l == r) {
		printf("U%d", l);
		return ;
	}
	putchar('(');
	print(l, rec[l][r]);
	print(rec[l][r] + 1, r);
	putchar(')');
}

void Mco() {
	for (int l = 2; l <= n; l++) {
		for (int i = 1; i <= n - l + 1; i++) {
			int j = i + l - 1;
			m[i][j] = 0x3f3f3f3f;
			for (int k = i; k < j; k++) {
				int q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
				if (q < m[i][j]) {
					m[i][j] = q;
					rec[i][j] = k;
				}
			}
		}
	}
	printf("MCO:%d\n", m[1][n]);
	print(1, n);
} 

int main() {
	/* 
	6
	2 3 7 9 5 2 4
	6
	30 35 15 5 10 20 25
	\*/
	cin >> n;
	for (int i = 0; i <= n; i++) cin >> p[i];
	Mco();
	
	return 0;
}

堆优化dijkstra

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int, int> PII;

const int N = 1e6 + 10;
int n, m;
int h[N], e[N], w[N], ne[N], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

int dijkstra() {
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    
    while (heap.size()) {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second, distance = t.first;
        
        if (st[ver]) continue;
        st[ver] = true;
        
        for (int i = h[ver]; i != -1; i = ne[i]) {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i]) {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

int main() {
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    
    while (m--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    printf("%d\n", dijkstra());
    return 0;
}

bellman-ford

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 510, M = 10010;

struct edge {
    int a, b, c;
} edges[M];

int n, m, k;
int dist[N];
int last[N];

void bellman_ford() {
    memset(dist, 0x3f, sizeof(dist));
    
    dist[1] = 0;
    for (int i = 0; i < k; i++) {
        memcpy(last, dist, sizeof(dist));
        for (int j = 0; j < m; j++) {
            struct edge e = edges[j];
            dist[e.b] = min(dist[e.b], last[e.a] + e.c);
        }
    }
}

int main() {
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edges[i] = {a, b, c};
    }
    
    bellman_ford();
    
    if (dist[n] > 0x3f3f3f3f / 2) puts("impossible");
    else printf("%d\n", dist[n]);
    
    return 0;
}

prim 求最小生成树

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int n, m;
int g[N][N];
int dist[N];
bool st[N];


int prim() {
    memset(dist, 0x3f, sizeof dist);

    int res = 0;
    for (int i = 0; i < n; i ++ ) {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        if (i && dist[t] == INF) return INF;

        if (i) res += dist[t];
        st[t] = true;

        for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);
    }

    return res;
}


int main() {
    scanf("%d%d", &n, &m);

    memset(g, 0x3f, sizeof g);

    while (m -- ) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = g[b][a] = min(g[a][b], c);
    }

    int t = prim();

    if (t == INF) puts("impossible");
    else printf("%d\n", t);

    return 0;
}

kruskal求最小生成树 (并查集优化)

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 200010;

struct edge {
    int s, e, v;
    bool operator< (const edge &b) const {
        return this->v < b.v;
    }
} edges[N];

int pred[N];
int preds[N];

int n, m, ans, cnt, p[N];

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}
string s = "0abcdfghiz";
string ss = "1 2 3 4 5 6 7 8 9";

/*
1 2 3 4 5 6 7 8 9 依次代表 a b c d f g h i z

输入:

9 14
1 2 4
1 7 8
2 7 1
2 3 8
7 8 7
7 6 1
6 8 4
8 3 2
3 4 7
3 5 4
6 5 2
5 4 14
4 9 9
5 9 10

*/
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) {
        cin >> edges[i].s >> edges[i].e >> edges[i].v;
    }
    sort(edges, edges + m);
    for (int i = 1; i <= n; i++) {
        p[i] = i;
    }
    
    for (int i = 0; i < m; i++) {
        int s = edges[i].s, e = edges[i].e, v = edges[i].v;
        int a = find(s), b = find(e);
        if (a != b) {
            p[a] = b;
            pred[e] = s;
            preds[e] = v;
            ans += v;
            cnt++;
        }
    }
    
    if (cnt == n - 1) {
        printf("%d\n", ans);
    } else {
        puts("impossible");
    }

    cout << "a b c d f g h i z" << endl;
    for (int i = 1; i <= n; i++) printf("%d ", preds[i]);
    puts("");
    for (int i = 1; i <= n; i++) printf("%c ", s[pred[i]]);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值