图的遍历与泛洪算法
图的遍历与泛洪算法
深度优先遍历;广度优先遍历;泛洪算法(Flood Fill)。
概念
在图或二维网格上,DFS/BFS 遍历访问所有从起点可达的结点;Flood Fill(泛洪/填充)是典型应用:从某格出发,把与之四连通(或八连通)且同色/同类的格子全部标记。本叶子考的是「连通性、遍历顺序、visited 数组、邻接关系」,与 cspj.algo.dfs-bfs 相邻:后者更抽象,可含非图题的状态搜索;这里题面更常出现邻接矩阵/表、网格 g[i][j]、连通块计数。与 cspj.ds.graph 区分:数据结构叶子讲存储方式,本叶子讲怎么用遍历解决问题。
CSP-J 常考
cspj-r1-2022第 40–44 题:完善程序,Flood Fill 或图遍历的多处空位(2022 完善程序·洪水填充题组)。cspj-r1-2023第 12 题:单选题,图的 DFS/BFS 或 Flood Fill 相关判断。
// Flood Fill:把与 (r,c) 四连通且值为 ch 的格子改为 '#'
void fill(char g[][], int r, int c, char ch) {
if (r < 0 || c < 0 || !in(r,c) || g[r][c] != ch) return;
g[r][c] = '#';
fill(g, r+1, c, ch);
fill(g, r-1, c, ch);
fill(g, r, c+1, ch);
fill(g, r, c-1, ch);
}
易错点
- 完善程序里递归 Flood Fill 边界判断写错,
r,n与c,m行列混淆。 - 把「遍历图」与「遍历树」等同:图要有 visited 防回边,树有时可不标记父节点但要看题意。
- 八连通与四连通搞混,阅读程序若数组偏移是 8 方向而题意是 4 方向,连通块大小会变。
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
现有用字符标记像素颜色的 8×8 图像。颜色填充的操作描述如下:给定起始像素的位置待填充的颜色,将起始像素和所有可达的像素(可达的定义:经过一次或多次的向上、下、左、右四个方向移动所能到达且终点和路径上所有像素的颜色都与起始像素颜色相同),替换为给定的颜色。
试补全程序。
#include<bits/stdc++.h>2using namespace std;34const int ROWS = 8;5const int COLS = 8;67struct Point {8 int r, c;9 Point(int r, int c): r(r), c(c) {}10};1112bool is_valid(char image[ROWS][COLS], Point pt,13 int prev_color, int new_color) {14 int r = pt.r;15 int c = pt.c;16 return (0 <= r && r < ROWS && 0 <= c && c < COLS &&17 ① && image[r][c] != new_color);18}1920void flood_fill(char image[ROWS][COLS], Point cur, int new_color) {21 queue<Point> queue;22 queue.push(cur);2324 int prev_color = image[cur.r][cur.c];25 ②;2627 while (!queue.empty()) {28 Point pt = queue.front ();29 queue.pop ();3031 Point points[4] = {③, Point(pt.r - 1, pt.c),32 Point(pt.r, pt.c + 1), Point(pt.r, pt.c - 1)};33 for (auto p : points) {34 if (is_valid(image, p, prev_color, new_color)) {35 ④;36 ⑤;37 }38 }39 }40}4142int main() {43 char image[ROWS][COLS] = {{'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g'},44 {'g', 'g', 'g', 'g', 'g', 'g', 'r', 'r'},45 {'g', 'r', 'r', 'g', 'g', 'r', 'g', 'g'},46 {'g', 'b', 'b', 'b', 'b', 'r', 'g', 'r'},47 {'g', 'g', 'g', 'b', 'b', 'r', 'g', 'r'},48 {'g', 'g', 'g', 'b', 'b', 'b', 'b', 'r'},49 {'g', 'g', 'g', 'g', 'g', 'b', 'g', 'g'},50 {'g', 'g', 'g', 'g', 'g', 'b', 'b', 'g'}};5152 Point cur(4, 4);53 char new_color = 'y';5455 flood_fill(image, cur, new_color);5657 for (int r = 0; r < ROWS; r++) {58 for (int c = 0; c < COLS; c++) {59 cout << image[r][c] << '';60 }61 cout << endl;62 }63//输出:64// g g g g g g g g65// g g g g g g r r66// g r r g g r g g67// g y y y y r g r68// g g g y y r g r69// g g g y y y y r70// g g g g g y g g71// g g g g g y y g7273 return 0;74}- 40(①)单选空位 ①3 分
① && image[r][c] != new_color)
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
现有用字符标记像素颜色的 8×8 图像。颜色填充的操作描述如下:给定起始像素的位置待填充的颜色,将起始像素和所有可达的像素(可达的定义:经过一次或多次的向上、下、左、右四个方向移动所能到达且终点和路径上所有像素的颜色都与起始像素颜色相同),替换为给定的颜色。
试补全程序。
#include<bits/stdc++.h>2using namespace std;34const int ROWS = 8;5const int COLS = 8;67struct Point {8 int r, c;9 Point(int r, int c): r(r), c(c) {}10};1112bool is_valid(char image[ROWS][COLS], Point pt,13 int prev_color, int new_color) {14 int r = pt.r;15 int c = pt.c;16 return (0 <= r && r < ROWS && 0 <= c && c < COLS &&17 ① && image[r][c] != new_color);18}1920void flood_fill(char image[ROWS][COLS], Point cur, int new_color) {21 queue<Point> queue;22 queue.push(cur);2324 int prev_color = image[cur.r][cur.c];25 ②;2627 while (!queue.empty()) {28 Point pt = queue.front ();29 queue.pop ();3031 Point points[4] = {③, Point(pt.r - 1, pt.c),32 Point(pt.r, pt.c + 1), Point(pt.r, pt.c - 1)};33 for (auto p : points) {34 if (is_valid(image, p, prev_color, new_color)) {35 ④;36 ⑤;37 }38 }39 }40}4142int main() {43 char image[ROWS][COLS] = {{'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g'},44 {'g', 'g', 'g', 'g', 'g', 'g', 'r', 'r'},45 {'g', 'r', 'r', 'g', 'g', 'r', 'g', 'g'},46 {'g', 'b', 'b', 'b', 'b', 'r', 'g', 'r'},47 {'g', 'g', 'g', 'b', 'b', 'r', 'g', 'r'},48 {'g', 'g', 'g', 'b', 'b', 'b', 'b', 'r'},49 {'g', 'g', 'g', 'g', 'g', 'b', 'g', 'g'},50 {'g', 'g', 'g', 'g', 'g', 'b', 'b', 'g'}};5152 Point cur(4, 4);53 char new_color = 'y';5455 flood_fill(image, cur, new_color);5657 for (int r = 0; r < ROWS; r++) {58 for (int c = 0; c < COLS; c++) {59 cout << image[r][c] << '';60 }61 cout << endl;62 }63//输出:64// g g g g g g g g65// g g g g g g r r66// g r r g g r g g67// g y y y y r g r68// g g g y y r g r69// g g g y y y y r70// g g g g g y g g71// g g g g g y y g7273 return 0;74}- 41(②)单选空位 ②3 分
int prev_color = image[cur.r][cur.c];
②;
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
现有用字符标记像素颜色的 8×8 图像。颜色填充的操作描述如下:给定起始像素的位置待填充的颜色,将起始像素和所有可达的像素(可达的定义:经过一次或多次的向上、下、左、右四个方向移动所能到达且终点和路径上所有像素的颜色都与起始像素颜色相同),替换为给定的颜色。
试补全程序。
#include<bits/stdc++.h>2using namespace std;34const int ROWS = 8;5const int COLS = 8;67struct Point {8 int r, c;9 Point(int r, int c): r(r), c(c) {}10};1112bool is_valid(char image[ROWS][COLS], Point pt,13 int prev_color, int new_color) {14 int r = pt.r;15 int c = pt.c;16 return (0 <= r && r < ROWS && 0 <= c && c < COLS &&17 ① && image[r][c] != new_color);18}1920void flood_fill(char image[ROWS][COLS], Point cur, int new_color) {21 queue<Point> queue;22 queue.push(cur);2324 int prev_color = image[cur.r][cur.c];25 ②;2627 while (!queue.empty()) {28 Point pt = queue.front ();29 queue.pop ();3031 Point points[4] = {③, Point(pt.r - 1, pt.c),32 Point(pt.r, pt.c + 1), Point(pt.r, pt.c - 1)};33 for (auto p : points) {34 if (is_valid(image, p, prev_color, new_color)) {35 ④;36 ⑤;37 }38 }39 }40}4142int main() {43 char image[ROWS][COLS] = {{'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g'},44 {'g', 'g', 'g', 'g', 'g', 'g', 'r', 'r'},45 {'g', 'r', 'r', 'g', 'g', 'r', 'g', 'g'},46 {'g', 'b', 'b', 'b', 'b', 'r', 'g', 'r'},47 {'g', 'g', 'g', 'b', 'b', 'r', 'g', 'r'},48 {'g', 'g', 'g', 'b', 'b', 'b', 'b', 'r'},49 {'g', 'g', 'g', 'g', 'g', 'b', 'g', 'g'},50 {'g', 'g', 'g', 'g', 'g', 'b', 'b', 'g'}};5152 Point cur(4, 4);53 char new_color = 'y';5455 flood_fill(image, cur, new_color);5657 for (int r = 0; r < ROWS; r++) {58 for (int c = 0; c < COLS; c++) {59 cout << image[r][c] << '';60 }61 cout << endl;62 }63//输出:64// g g g g g g g g65// g g g g g g r r66// g r r g g r g g67// g y y y y r g r68// g g g y y r g r69// g g g y y y y r70// g g g g g y g g71// g g g g g y y g7273 return 0;74}- 42(③)单选空位 ③3 分
Point points[4] = {③, Point(pt.r - 1, pt.c),
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
现有用字符标记像素颜色的 8×8 图像。颜色填充的操作描述如下:给定起始像素的位置待填充的颜色,将起始像素和所有可达的像素(可达的定义:经过一次或多次的向上、下、左、右四个方向移动所能到达且终点和路径上所有像素的颜色都与起始像素颜色相同),替换为给定的颜色。
试补全程序。
#include<bits/stdc++.h>2using namespace std;34const int ROWS = 8;5const int COLS = 8;67struct Point {8 int r, c;9 Point(int r, int c): r(r), c(c) {}10};1112bool is_valid(char image[ROWS][COLS], Point pt,13 int prev_color, int new_color) {14 int r = pt.r;15 int c = pt.c;16 return (0 <= r && r < ROWS && 0 <= c && c < COLS &&17 ① && image[r][c] != new_color);18}1920void flood_fill(char image[ROWS][COLS], Point cur, int new_color) {21 queue<Point> queue;22 queue.push(cur);2324 int prev_color = image[cur.r][cur.c];25 ②;2627 while (!queue.empty()) {28 Point pt = queue.front ();29 queue.pop ();3031 Point points[4] = {③, Point(pt.r - 1, pt.c),32 Point(pt.r, pt.c + 1), Point(pt.r, pt.c - 1)};33 for (auto p : points) {34 if (is_valid(image, p, prev_color, new_color)) {35 ④;36 ⑤;37 }38 }39 }40}4142int main() {43 char image[ROWS][COLS] = {{'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g'},44 {'g', 'g', 'g', 'g', 'g', 'g', 'r', 'r'},45 {'g', 'r', 'r', 'g', 'g', 'r', 'g', 'g'},46 {'g', 'b', 'b', 'b', 'b', 'r', 'g', 'r'},47 {'g', 'g', 'g', 'b', 'b', 'r', 'g', 'r'},48 {'g', 'g', 'g', 'b', 'b', 'b', 'b', 'r'},49 {'g', 'g', 'g', 'g', 'g', 'b', 'g', 'g'},50 {'g', 'g', 'g', 'g', 'g', 'b', 'b', 'g'}};5152 Point cur(4, 4);53 char new_color = 'y';5455 flood_fill(image, cur, new_color);5657 for (int r = 0; r < ROWS; r++) {58 for (int c = 0; c < COLS; c++) {59 cout << image[r][c] << '';60 }61 cout << endl;62 }63//输出:64// g g g g g g g g65// g g g g g g r r66// g r r g g r g g67// g y y y y r g r68// g g g y y r g r69// g g g y y y y r70// g g g g g y g g71// g g g g g y y g7273 return 0;74}- 43(④)单选空位 ④3 分
④;
整组作答后提交批改,成绩计入掌握度 · 已答 0/1
现有用字符标记像素颜色的 8×8 图像。颜色填充的操作描述如下:给定起始像素的位置待填充的颜色,将起始像素和所有可达的像素(可达的定义:经过一次或多次的向上、下、左、右四个方向移动所能到达且终点和路径上所有像素的颜色都与起始像素颜色相同),替换为给定的颜色。
试补全程序。
#include<bits/stdc++.h>2using namespace std;34const int ROWS = 8;5const int COLS = 8;67struct Point {8 int r, c;9 Point(int r, int c): r(r), c(c) {}10};1112bool is_valid(char image[ROWS][COLS], Point pt,13 int prev_color, int new_color) {14 int r = pt.r;15 int c = pt.c;16 return (0 <= r && r < ROWS && 0 <= c && c < COLS &&17 ① && image[r][c] != new_color);18}1920void flood_fill(char image[ROWS][COLS], Point cur, int new_color) {21 queue<Point> queue;22 queue.push(cur);2324 int prev_color = image[cur.r][cur.c];25 ②;2627 while (!queue.empty()) {28 Point pt = queue.front ();29 queue.pop ();3031 Point points[4] = {③, Point(pt.r - 1, pt.c),32 Point(pt.r, pt.c + 1), Point(pt.r, pt.c - 1)};33 for (auto p : points) {34 if (is_valid(image, p, prev_color, new_color)) {35 ④;36 ⑤;37 }38 }39 }40}4142int main() {43 char image[ROWS][COLS] = {{'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g'},44 {'g', 'g', 'g', 'g', 'g', 'g', 'r', 'r'},45 {'g', 'r', 'r', 'g', 'g', 'r', 'g', 'g'},46 {'g', 'b', 'b', 'b', 'b', 'r', 'g', 'r'},47 {'g', 'g', 'g', 'b', 'b', 'r', 'g', 'r'},48 {'g', 'g', 'g', 'b', 'b', 'b', 'b', 'r'},49 {'g', 'g', 'g', 'g', 'g', 'b', 'g', 'g'},50 {'g', 'g', 'g', 'g', 'g', 'b', 'b', 'g'}};5152 Point cur(4, 4);53 char new_color = 'y';5455 flood_fill(image, cur, new_color);5657 for (int r = 0; r < ROWS; r++) {58 for (int c = 0; c < COLS; c++) {59 cout << image[r][c] << '';60 }61 cout << endl;62 }63//输出:64// g g g g g g g g65// g g g g g g r r66// g r r g g r g g67// g y y y y r g r68// g g g y y r g r69// g g g y y y y r70// g g g g g y g g71// g g g g g y y g7273 return 0;74}- 44(⑤)单选空位 ⑤3 分
⑤;
考虑一个有向无环图,该图包含 4 条有向边:(1,2),(1,3),(2,4) 和 (3,4)。以下哪个选项是这个有向无环图的一个有效的拓扑排序?