> 文章列表 > 2023 算法设计与分析 (计算机与网安)第三次实验课

2023 算法设计与分析 (计算机与网安)第三次实验课

2023 算法设计与分析 (计算机与网安)第三次实验课

目录

1. BFS试炼之微博转发

2. DFS试炼之不同路径数

3. 并查集试炼之合并集合

4. 堆排序

5. 厦大GPA

6. 消防安全指挥问题

7. 铺设光纤问题

8. CCF A会报

9. 商店 (挑战题)


1. BFS试炼之微博转发

Tag:bfs

存储:邻接表

思路:有搜索层数限制,用dist数组记录层数,超出要求则continue

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
using namespace std;const int N = 1005;
int n, l;
int e[N], ne[N], h[N], idx, dist[N];
bool st[N];
queue<int> q;void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}int bfs(int x) {memset(st, 0, sizeof st);memset(dist, 0, sizeof dist);q.push(x);st[x] = true;int cnt = 0;while (q.size()) {auto t = q.front();q.pop();for (int i = h[t]; i != -1; i = ne[i]) {int j = e[i]; //cout << j << endl;if (st[j]) continue;dist[j] = dist[t] + 1;if (dist[j] > l)  continue;++ cnt;q.push(j);st[j] = true;}}return cnt;
}int main() {memset(h, -1, sizeof h);cin >> n >> l;for (int i = 1; i <= n; ++ i) {int num, x;cin >> num;for (int j = 0; j < num; ++ j) {cin >> x;add(x, i);//	cout << x << ' ' << i << endl;}}int t;cin >> t;while (t --) {int x;cin >> x;cout << bfs(x) << endl;}return 0;
}

2. DFS试炼之不同路径数

Tag:dfs,字符串哈希

思路:以每个点为起点dfs搜索。用字符串哈希记录不重复路径数。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<unordered_set>
using namespace std;const int N = 7;
char g[N][N];
bool st[N][N];
int n, m, k, ans;
unordered_set<string> s;
char str[10];void dfs(int x, int y, int u) {if (u > k) {//cout << str << endl;if (!s.count(str)) {s.insert(str);++ ans;}return;}st[x][y] = true;str[u] = g[x][y];//cout << u << ' ' << str << endl;int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};for (int i = 0; i < 4; ++ i) {int xx = x + dx[i], yy = y + dy[i];if (xx < 0 || xx >= n || yy < 0 || yy >= m) continue;dfs(xx, yy, u + 1);}
}int main() {cin >> n >> m >> k;for (int i = 0; i < n; ++ i)for (int j = 0; j < m; ++ j)cin >> g[i][j];for (int i = 0; i < n; ++ i) {for (int j = 0; j < m; ++ j) {memset(st, 0, sizeof st);dfs(i, j, 0);}}cout << ans << endl;return 0;
}

3. 并查集试炼之合并集合

Tag: 并查集

思路:模板题

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;const int N = 1e5 + 5;
int p[N];
int n, m;int find(int x) {return x == p[x] ? x : p[x] = find(p[x]);
}int main() {cin >> n >> m;for (int i = 1; i <= n; ++ i) p[i] = i;while (m --) {char c;int x, y;cin >> c >> x >> y;if (c == 'M') {if (find(x) != find(y)) p[find(x)] = find(y);} else {if (find(x) == find(y)) puts("Yes");else puts("No");}}return 0;
}

4. 堆排序

略。用sort混过去了。

5. 厦大GPA

Tag:分组背包、(贪心)

思路:

        绩点是价值,分数是体积,总分是容积。

        分组背包问题,4组,每组可以取一个分数。

        (前置处理写麻烦了,贪心只用每个档的最低分数数据就可以了)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;//绩点是价值 分数是体积 总分是容积
//分组背包问题 4组 每组可以取一个分数const int N = 405;
int v[N], w[N];
int f[N];void init() {for (int i = 1, s = 0; s <= 100;) {switch (s) {case 0:for (; s <= 59; ++i, ++s) v[i] = s, w[i] = 0;break;case 60:for (; s <= 63; ++i, ++s) v[i] = s, w[i] = 10;break;case 64:for (; s <= 67; ++i, ++s) v[i] = s, w[i] = 17;break;case 68:for (; s <= 71; ++i, ++s) v[i] = s, w[i] = 20;break;case 72:for (; s <= 74; ++i, ++s) v[i] = s, w[i] = 23;break;case 75:for (; s <= 77; ++i, ++s) v[i] = s, w[i] = 27;break;case 78:for (; s <= 80; ++i, ++s) v[i] = s, w[i] = 30;break;case 81:for (; s <= 84; ++i, ++s) v[i] = s, w[i] = 33;break;case 85:for (; s <= 89; ++i, ++s) v[i] = s, w[i] = 37;break;case 90:for (; s <= 100; ++i, ++s) v[i] = s, w[i] = 40;break;}}
}int main() {init();
//for(int i=1; i<=101; ++ i) printf("%d %d\\n", v[i], w[i]);int m;while (cin >> m) {memset(f, 0, sizeof f);for (int i = 1; i <= 4; ++ i) {for (int j = m; j >= 0; -- j) {for (int k = 1; k <= 101; ++ k)if (v[k] <= j)f[j] = max(f[j], f[j - v[k]] + w[k]);//cout << f[i][j] << endl;}}double res = f[m] / 10.0;//cout << res << endl;printf("%.1f\\n", res);}return 0;
}

 

6. 消防安全指挥问题

Tag:dijkstra

思路:对消防队在的位置为起点dijkstra,比较取最短。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;const int N = 1005;
int xfd[N];
int n, m, p, q;
int g[N][N], dist[N];
bool st[N];int dijkstra(int x) {memset(dist, 0x3f, sizeof dist);memset(st, 0, sizeof st);dist[x] = 0;//cout << m << endl;for (int i = 0; i < m; ++ i) {int t = -1, dis = 0x3f3f3f3f;for (int j = 1; j <= m; ++ j) {if (!st[j] && (t == -1 || dist[j] < dis)) {t = j;dis = dist[j];}}
//cout << t << endl;st[t] = true;  if (t == q) return dist[q];for (int i = 1; i <= m; ++ i) dist[i] = min(dist[i], dist[t] + g[t][i]);}return 0x3f3f3f3f;
}int main() {int t;cin >> t;while (t --) {cin >> n >> m >> p >> q; memset(g, 0x3f, sizeof g);for (int i = 0; i < n; ++i) cin >> xfd[i];while (p --) {int a, b, w;cin >> a >> b >> w;g[a][b] = g[b][a]= min(g[a][b], w);}int ans = 0x3f3f3f3f;for (int i = 0; i < n; ++ i) {//cout <<m << endl;ans = min(ans, dijkstra(xfd[i]));//cout << ans << endl;}cout << ans << endl;}return 0;
}

 

7. 铺设光纤问题

Tag:prim

思路:模板题。纳入未标记的离现有的一团点距离最近的点。dist存的是到当前这团点的距离。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;const int N = 105;
int g[N][N], dist[N];
int n, ans;
bool st[N];void prim() {memset(dist, 0x3f, sizeof dist);dist[1] = 0;for (int i = 0; i < n; ++ i) {int dis = 0x3f3f3f3f, t;for (int j = 1; j <= n; ++ j) {if (!st[j] && dist[j] < dis) {dis = dist[j];t = j;}}st[t] = true;ans += dist[t];for (int i = 1; i <= n; ++i) dist[i] = min(dist[i], g[t][i]);}
}int main() {cin >> n;for (int i = 1; i <= n; ++ i)for (int j = 1; j <= n; ++ j)cin >> g[i][j];prim();cout << ans << endl;return 0;
}

8. CCF A会报告

Tag:多重背包

思路:模板题。除种类体积外,再循环每个品类的个数。注意判是否小于等于容积。

拓展:如果s[]的范围增大,则可以考虑二进制打包优化。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;const int N = 6005;
int v[N], w[N], s[N];
int n, m;
int f[N];int main() {cin >> n >> m;for (int i = 1; i <= n; ++ i) {cin >> v[i] >> w[i] >> s[i];}for (int i = 1; i <= n; ++ i) {for (int j = m; j >= v[i]; -- j) {for (int k = 1; k <= s[i]; ++ k) {if (k * v[i] <= j)f[j] = max(f[j], f[j - k * v[i]] + k * w[i]);}}}cout << f[m] << endl;return 0;
}

9. 商店 (挑战题)

Tag:贪心

存储:优先队列小根堆

思路:
    贪心:为了满足尽可能多的预订单,每次应优先处理商品数少的订单
               又因为当天的货物只可以被当天的订单和后续的订单消耗,所以可以倒序处理数据
    核心:用当前的供应量增序处理队列中的剩余订单

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;#define out first
#define index second 
typedef pair<int, int> PII;
const int N = 3e5 + 5;
priority_queue<PII, vector<PII>, greater<PII> > q;
int in[N], out[N];
int n, res;int main() {cin >> n;for (int i = 1; i <= n; ++ i)  cin >> in[i] >> out[i];for(int i=n; i; --i){int cur = in[i];q.push({out[i], i});while(q.size()){auto t = q.top();q.pop();int csm = min(t.out, cur);cur -= csm;t.out -= csm;if(t.out == 0) ++ res;else q.push(t);if(cur == 0) break;}}cout << res << endl;return 0;
}