#define x first #define y second typedef pair<int, int> pii;
constint N = 1010; int n, m, dx[] = {0, 1, 1, 1, 0, -1, -1, -1}, dy[] = {1, 1, 0, -1, -1, -1, 0, 1}; char g[N][N]; bool st[N][N]; queue<pii> q;
voidbfs(int x, int y){ st[x][y] = true; q.push({x, y}); while (q.size()) { pii p = q.front(); q.pop(); for (int i = 0; i < 8; i++) { pii ne = {p.x+dx[i], p.y+dy[i]}; if (0 <= ne.x && ne.x < n && 0 <= ne.y && ne.y < m && g[ne.x][ne.y] == 'W' && !st[ne.x][ne.y]) { q.push(ne); // 这里提前标记,不要在上面弹队列的时候再标记,否则复杂度飙升 st[ne.x][ne.y] = true; } } } }
intmain(){ cin >> n >> m; for (int i = 0; i < n; i++) cin >> g[i]; int cnt = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (!st[i][j] && g[i][j] == 'W') bfs(i, j), cnt++; } } cout << cnt; return0; }
房间划分
请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。
城堡被分割成 m*n 个方格区域,每个方格区域可以有0~4面墙。
每个方块中墙的特征由数字 P 来描述,我们用1表示西墙,2表示北墙,4表示东墙,8表示南墙,P 为该方块包含墙的数字之和。例如,如果一个方块的 P 为3,则 3 = 1 + 2,该方块包含西墙和北墙。
typedef pair<int, int> pii; constint N = 55; int g[N][N], m, n, dx[] = {0, -1, 0, 1}, dy[] = {-1, 0, 1, 0}, mask[] = {1, 1<<1, 1<<2, 1<<3}; bool st[N][N]; queue<pii> q;
intbfs(int i, int j){ st[i][j] = true; int cnt = 0; q.push({i, j}); while (q.size()) { pii p = q.front(); q.pop(); cnt++; for (int i = 0; i < 4; i++) { int px = p.first, py = p.second; int x = px+dx[i], y=py+dy[i]; // 这里如果到达边界数据保证是一定有墙的 // 因此只需要判断当前格子的这个方向有没有墙就行 if (!st[x][y] && (mask[i] & g[px][py]) == 0) { st[x][y] = true; q.push({x, y}); } } } return cnt; }
intmain(){ cin >> m >> n; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) cin >> g[i][j]; int area = 0, cnt = 0; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) if (!st[i][j]) area = max(area, bfs(i, j)), cnt++; cout << cnt << endl << area << endl; return0; }
voidbfs(){ st[init.x][init.y] = true; q.push(init); while (q.size()) { pii p = q.front(); q.pop(); if (p == target) break; for (int i = 0; i < 8; i++) { int x = p.x+dx[i], y = p.y+dy[i]; // 这里 n 和 m 一定要看清楚 if (x < 0 || x >= n || y < 0 || y >= m || st[x][y] || g[x][y]) continue; st[x][y] = true; dist[x][y] = dist[p.x][p.y]+1; q.push({x, y}); } } }
intmain(){ cin >> m >> n; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) { char ch; cin >> ch; if (ch == '*') g[i][j] = true; elseif (ch == 'K') init = {i, j}; elseif (ch == 'H') target = {i, j}; } bfs(); cout << dist[target.x][target.y]; return0; }
constint N = 1e5+10; int n, m; int h[N], e[N], ne[N], idx, q[N], d[N]; bitset<N> st;
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
intbfs(){ int tt = -1, hh = 0; q[++tt] = 1; memset(d, -1, sizeof d); d[1] = 0; while (hh <= tt) { int t = q[hh++]; st[t] = 1; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j] && d[j] == -1) { d[j] = d[t] + 1; q[++tt] = j; } } } return d[n]; }
intmain(){ // 不要忘记初始化树!! memset(h, -1, sizeof h); cin >> n >> m; int a, b; for (int i = 0; i < m; i++) { cin >> a >> b; add(a, b); } cout << bfs() << endl; return0; }
#define x first #define y second typedef pair<int, int> pii; constint N = 1010;
int n, m, dist[N][N], dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1}; bool g[N][N]; queue<pii> q;
voidbfs(){ while (q.size()) { pii p = q.front(); q.pop(); for (int i = 0; i < 4; i++) { int x = p.x+dx[i], y = p.y+dy[i]; if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] || dist[x][y] != -1) continue; dist[x][y] = dist[p.x][p.y]+1; q.push({x, y}); } } }
intmain(){ cin >> n >> m; memset(dist, -1, sizeof dist); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { char ch; cin >> ch; g[i][j] = ch == '1'; if (g[i][j]) { dist[i][j] = 0; q.push({i, j}); } } } bfs(); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cout << dist[i][j] << ' '; } cout << '\n'; } return0; }
#define x first #define y second typedef pair<int, int> pii; constint N = 510;
char g[N][N]; int dx[] = {-1, 1, 1, -1}, dy[] = {1, 1, -1, -1}; int bx[] = {-1, 0, 0, -1}, by[] = {0, 0, -1, -1}; // zero cost char zc[] = {'/', '\\', '/', '\\'}; bool st[N][N]; int dist[N][N], n, m;
intdj(){ // 执行完本函数 q 不一定是非空的,因此这里就把 q 申请为局部变量 deque<pii> q; q.push_back({0, 0}); memset(dist, 0x3f, sizeof dist); memset(st, 0, sizeof st); dist[0][0] = 0; while (q.size()) { pii p = q.front(); q.pop_front(); if (p.x == n && p.y == m) return dist[n][m]; if (st[p.x][p.y]) continue; st[p.x][p.y] = true;
for (int i = 0; i < 4; i++) { int x = p.x+dx[i], y = p.y+dy[i], w = 1; // 注意 m 和 n。。。 if (x < 0 || x > n || y < 0 || y > m) continue; if (zc[i] == g[p.x+bx[i]][p.y+by[i]]) w = 0; int d = dist[p.x][p.y]+w; // 这里大于和大于等于都可以 if (dist[x][y] > d) { dist[x][y] = d; if (w == 0) q.push_front({x, y}); else q.push_back({x, y}); } } } return-1; }
intmain(){ int T; cin >> T; while (T--) { // 格子坐标 0 ~ n-1, 0 ~ m-1 // 点坐标 0 ~ n, 0 ~ m cin >> n >> m; for (int i = 0; i < n; i++) cin >> g[i]; int res = dj(); if (res == -1) cout << "NO SOLUTION\n"; else cout << res << '\n'; } return0; }
#define x first #define y second typedef pair<int, int> PII; constint M = 110; int n, m; PII p[M];
intsolve(){ sort(p, p+m); int res = 0; for (int i = 0; i < m; i++) { int up = n+1, down = 0; for (int j = i+1; j < m; j++) { if (p[j].x == p[i].x) continue; // 这里也可以优化一条 // if (p[j].x - p[i].x > up - down) break; // 因为我们这里是关心横坐标对边长的限制 纵坐标应该是对称之后该关心的 // 但这只能算是常数优化, 不加也无所谓 res = max(res, min(p[j].x - p[i].x - 1, up - down - 1)); if (p[j].y >= p[i].y) up = min(up, p[j].y); if (p[j].y <= p[i].y) down = max(down, p[j].y); } } return res; }
intmain(){ scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) scanf("%d%d", &p[i].x, &p[i].y); p[m++] = {0, 0}; p[m++] = {0, n+1}; p[m++] = {n+1, 0}; p[m++] = {n+1, n+1}; int res = solve(); for (int i = 0; i < m; i++) swap(p[i].x, p[i].y); printf("%d\n", max(res, solve())); return0; }
八数码
在一个 3x3 的网格中,1∼8 这 8 个数字和一个 x 恰好不重不漏地分布在这 3x3 的网格中。
例如:
1 2 3
1 2 3 x 4 6 7 5 8
在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。
我们的目的是通过交换,使得网格变为如下排列(称为正确排列):
1 2 3
1 2 3 4 5 6 7 8 x
例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。
交换过程如下:
1 2 3
1 2 3 1 2 3 1 2 3 1 2 3 x 4 6 4 x 6 4 5 6 4 5 6 7 5 8 7 5 8 7 x 8 7 8 x