AcWing 第 13 場周賽 補題記錄
阿新 • • 發佈:2021-08-23
比賽連結:Here
AcWing 3811. 排列
簽到題,
先輸出 \(n\) 然後輸出 \(1\sim n -1\) 即可
AcWing 3812. 機器人走迷宮
不會什麼特別高階的方法 qaq,只能全排列 + bfs(懶得寫太長了,註釋寫程式碼裡 qaq)
#include <bits/stdc++.h> #define rep(a,b,c) for (int i = a; i <= b; i += c) #define rept(i,a,b,c) for (int i = a; i <= b; i += c) using namespace std; const int N = 1e3 + 5, INF = INFINITY; int n, m, a[N][N]; string st; int sx, sy, fx, fy; void init () { cin >> n >> m; rep (1, n, 1) rept (j, 1, m, 1) { char ch; cin >> ch; a[i][j] = (ch == '#'); if (ch == 'S') sx = i, sy = j; if (ch == 'E') fx = i, fy = j; // 起點 終點 } cin >> st; } int mx[] = {0, 0, -1, 1}, my[] = {-1, 1, 0, 0}, mtx[50]; // mtx 表示對應 0~3 的分配 struct Node { int x, y, step; }; bool bfs () { // 廣搜模板不需要太多解釋 queue<Node> q; q.push ({sx, sy, 0}); while (!q.empty()) { Node tp = q.front(); q.pop(); int x = tp.x, y = tp.y, sp = tp.step; if (x == fx && y == fy && sp <= st.size()) return 1; int M = mtx[st[sp] & 15]; // 位運算,等價於 M = mtx[st[sp] - 48] x += mx[M], y += my[M], sp ++; if (!(x && y && x <= n && y <= m && !a[x][y])) return 0;// 如果撞牆/越界就送走( q.push ({x, y, sp}); } return 0; } void solve() { mtx[0] = 0; mtx[1] = 1; mtx[2] = 2; mtx[3] = 3; int res = 0; do res += bfs(); /*可以到達終點 方案 + 1*/ while (next_permutation (mtx, mtx + 4)); // 全排列 printf ("%d\n", res); return ; } int main() { int T; cin >> T; while (T --) init(), solve(); return 0; }
AcWing 3813. 最大路徑權值
拆點 + topsort
拆點: \(dist[N][26]\) 把每個點拆成 \(26\) 個點, 分別表示到當前點的路徑上, 每個字母的最大值
topsort:找環, 判掉有環的情況, 我們可以發現, 無論最長路徑的字母是哪個字母, 我們都可以從該路徑對應的拓撲序的第一個點開始遍歷, 所以只要按照拓撲序線性遞推就行了
const int N = 3e5 + 10, M = 5e5; int h[N], e[M], ne[M], idx; int dist[N][30]; int d[N]; typedef pair<int, int> PII; int hh = 0, tt = -1; bool st[N]; int q[N]; int w[N]; int n, m; void add(int a, int b) { // 新增一條邊a->b e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } bool topsort() { // d[i] 儲存點i的入度 for (int i = 1; i <= n; i ++ ) if (!d[i]) q[ ++ tt] = i; while (hh <= tt) { int t = q[hh ++ ]; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (-- d[j] == 0) q[ ++ tt] = j; } } // 如果所有點都入隊了,說明存在拓撲序列;否則不存在拓撲序列。 return tt == n - 1; } int main() { scanf("%d%d", &n, &m); string tmp; cin >> tmp; memset(h, -1, sizeof h); for (int i = 1; i <= n; i ++ ) { int x = tmp[i - 1] - 'a'; w[i] = x; } while (m -- ) { int a, b; scanf("%d%d", &a, &b); add(a, b); d[b] ++; } for (int i = 1; i <= n; i ++ ) { if (!d[i]) { dist[i][w[i]] = 1; } } bool flag = topsort(); if (!flag) { puts("-1"); return 0; } for (int i = 0; i <= tt; i ++ ) { int j = q[i]; for (int u = h[j]; ~u; u = ne[u]) { int k = e[u]; for (int v = 0; v < 26; v ++ ) { dist[k][v] = max(dist[k][v], dist[j][v] + (w[k] == v)); } } } int ans = 0; for (int i = 1; i <= n; i ++ ) { for (int j = 0; j < 26; j ++ ) { ans = max(ans, dist[i][j]); } } printf("%d", ans); return 0; }
The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。