# 第一题是打印一种旋转标号的矩阵
硬做,其中一些 if () 中的判断条件好像有多余,但为了赶时间,结果对就不改了
#include <bits/stdc++.h> using namespace std; const int N = 210; int n; int w[N][N]; int main() { scanf("%d", &n); int len = n / 2; if (n % 2) { for (int i = 1; i <= n; ++ i) { for (int j = 1; j <= n; ++ j) { if (i < len + 1 && j < len + 1 && j > i) w[i][j] = 2; else if (i < len + 1 && j > len + 1 && i + j <= n) w[i][j] = 1; else if (i < len + 1 && j < i ) w[i][j] = 3; else if (i < len + 1 && j > len + 1 && i + j > n + 1) w[i][j] = 8; else if (i > len + 1 && j < len + 1 && i + j <= n) w[i][j] = 4; else if (i > len + 1 && j > len + 1 && i < j) w[i][j] = 7; else if (i > len + 1 && j < len + 1 && i + j > n + 1) w[i][j] = 5; else if (i > len + 1 && j > len + 1 && j < i) w[i][j] = 6; } } } else { for (int i = 1; i <= n; ++ i) { for (int j = 1; j <= n; ++ j) { if (i < len && j <= len && j > i) w[i][j] = 2; else if (i < len && j >= len && i + j <= n) w[i][j] = 1; else if (i <= len && j < i ) w[i][j] = 3; else if (i <= len && j > n - i + 1) w[i][j] = 8; else if (i >= len + 1 && j <= -i + n) w[i][j] = 4; else if (i >= len + 1 && j > i) w[i][j] = 7; else if (i > len + 1 && j <= len && i + j > n + 1) w[i][j] = 5; else if (i > len + 1 && j >= len + 1 && j < i) w[i][j] = 6; } } } for (int i = 1; i <= n; ++ i) { for (int j = 1; j <= n; ++ j) { printf("%d ", w[i][j]); } puts(""); } }# 第二题,棋盘中移动一个点,使得连通块最大
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 410; int n, m; int g[N][N]; // g[][] 存储原图 int w[N][N], idx; // w[][] 存储每个连通块的编号 idx bool st[N][N]; // 表示每个点是否被遍历过 PII q[N * N]; // 数组模拟队列 int cnt[N * N]; // 记录每个连通块中点的个数 int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; // 将一个连通块扫描出来,全部标记为 idx void bfs(int sx, int sy) { q[0] = {sx, sy}; w[sx][sy] = idx; st[sx][sy] = true; int hh = 0, tt = 0; while (hh <= tt) { PII t = q[hh ++ ]; // 队头元素出队列 int x = t.first, y = t.second; // x 横坐标,y 纵坐标 ++ cnt[idx]; // 连通块中数量加 1 for (int d = 0; d < 4; ++ d) { // 循环 4 个方向 int xx = x + dx[d], yy = y + dy[d]; if (xx < 0 || xx >= n || yy < 0 || yy >= m) continue; if (g[xx][yy] == 0 || st[xx][yy]) continue; w[xx][yy] = idx; // 点 (xx, yy) 所在连通块的编号标记为 idx q[ ++ tt] = {xx, yy}; // 新的点加入队列 st[xx][yy] = true; // 标记为这个点已经被加入过队列 } } } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; ++ i) { for (int j = 0; j < m; ++ j) { scanf("%d", &g[i][j]); } } for (int i = 0; i < n; ++ i) { for (int j = 0; j < m; ++ j) { if (!g[i][j]) continue; if (st[i][j]) continue; ++ idx; bfs(i, j); // 开始扫描连通块 } } int res = 0; // 最终答案 // i j 循环枚举每一个可以放棋子的点 (w[][] 中标记为 0 的点) for (int i = 0; i < n; ++ i) { for (int j = 0; j < m; ++ j) { if (w[i][j]) continue; int ans = 0; // ans 记录在这个点落一个转移的棋子能形成多大连通块 set<int> st; // set集合 标记这个落棋子点周围有哪些连通块的编号 for (int d = 0; d < 4; ++ d) { int x = i + dx[d], y = j + dy[d]; if (x < 0 || x >= n || y < 0 || y >= m) continue; if (!w[x][y]) continue; if (st.count(w[x][y])) continue; ans += cnt[w[x][y]]; // ans 加上这个连通块中的所有棋子 st.insert(w[x][y]); } // 如果这个棋子落点能接触到的连通块数量 < 所有连通块数量 // 则加上转移过来的这个棋子 if (st.size() < idx) ++ans; res = max(res, ans); } } printf("%d\n", res); }# 第三题特殊的背包问题,只过了正常的情形,负数情形没过,求答案
全部评论
(5) 回帖