1329:【例8.2】细胞
【题目描述】
一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。如:阵列
有4个细胞。
【题目分析】
遍历所有节点,当无标识且不为零,进行深度优先搜索
深搜函数创建队列,对每个满足要求的节点(没有超过边界,无标识,非零)的加入队列,并进行标识
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int m, n;
int a[105][105];
int vis[105][105];
int _count = 0;
int _next[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
void bfs(int x, int y) { //行是x 列是y
queue<pair<int, int>>que;
que.push(make_pair(x, y));
vis[x][y] = 1;
while (!que.empty()) {
int px = que.front().first;
int py = que.front().second;
for (int i = 0; i < 4; i++) {
int nx = px + _next[i][0];
int ny = py + _next[i][1];
if (nx >= 1 && nx <= m && ny >= 1 && ny <= n && vis[nx][ny] == 0 && a[nx][ny] > 0) {
vis[nx][ny] = 1;
que.push(make_pair(nx, ny));
}
}
que.pop();
}
}
int main() {
//input data
cin >> m >> n;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
char ch;
cin >> ch;
a[i][j] = ch - '0';
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (vis[i][j] == 0 && a[i][j] > 0) {
_count++;
bfs(i, j);
}
}
}
cout << _count << endl;
return 0;
}
1330:【例8.3】最少步数
【题目描述】
在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100×100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。
【题目分析】
1、每一步有8+4=12种走法,使用结构体记录走的步数和点位,当前点的步数等于前一个点的步数+1
2、每一步判断有无标识,判断越界,从队列中取数的时候判断是否到达终点
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int L;
struct node {
int x;
int y;
int step;
node() {};
node(int _x, int _y, int _step): x(_x), y(_y), step(_step) {};
} p1;
int vis[305][305];
int _next[12][2] = { {1, 2}, {1, -2}, {2, 1}, {2, -1}, {-1, 2}, {-1, -2}, {-2, 1}, {-2, -1},
{2, 2}, {2, -2}, {-2, 2}, {-2, -2}
};
void bfs() {
memset(vis, 0, sizeof(vis));
queue<node>que;
que.push(p1);
vis[p1.x][p1.y] = 1;
while (!que.empty()) {
int x = que.front().x;
int y = que.front().y;
int s = que.front().step;
if (x == 1 && y == 1) {
cout << s << endl;
break;
}
for (int i = 0; i < 12; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
if (nx >= 1 && ny >= 1 && nx <= 100 && ny <= 100 && vis[nx][ny] == 0) {
vis[nx][ny] = 1;
que.push(node(nx, ny, s + 1));
}
}
que.pop();
}
}
int main() {
//input data
int x, y;
cin >> x >> y;
p1 = node(x, y, 0);
bfs();
cin >> x >> y;
p1 = node(x, y, 0);
bfs();
return 0;
}
1248:Dungeon Master
【题目描述】
这题是一个三维的迷宫题目,其中用‘.’表示空地,‘#’表示障碍物,‘S’表示起点,‘E’表示终点,求从起点到终点的最小移动次数,解法和二维的类似,只是在行动时除了东南西北移动外还多了上下。可以上下左右前后移动,每次都只能移到相邻的空位,每次需要花费一分钟,求从起点到终点最少要多久。
【题目分析】
1、创建一个含有x,y,z,step的结构体记录过程点位,标识数组也为三维
2、读入数据,找到起点和终点p1和p2,并将终点设为".",使用三维数组记录点位
3、将起点加入队列,每一步具有6个方向的移动,判断是否越界、是否已经标识,当前点的步数等于前一个点位步数+1
4、在出队的过程中判断是否到达终点,到达终点直接输出步数s
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int ceng, chang, kuan;
int a[105][105][105];
struct node {
int x, y, z;
int step;
node() {};
node(int _z, int _y, int _x, int _step): x(_x), y(_y), z(_z), step(_step) {};
} p1, p2;
bool vis[105][105][105];
int _next[6][3] = {{0, -1, 0}, {-1, 0, 0}, {0, 1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0, -1}};
void bfs() {
memset(vis, 0, sizeof(vis));
queue<node> que;
que.push(p1);
vis[p1.x][p1.y][p1.z] = 1;
bool flag = 1;
while (!que.empty()) {
int x = que.front().x; //宽
int y = que.front().y; //长
int z = que.front().z; //层
int s = que.front().step;
// printf("(%d,%d,%d)\n",x,y,z);
if (x == p2.x && y == p2.y && z == p2.z) {
printf("Escaped in %d minute(s).\n", s);
flag = 0;
break;
}
for (int i = 0; i < 6; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
int nz = z + _next[i][2];
if (nx < 1 || nx > kuan || ny < 1 || ny > chang || nz < 1 || nz > ceng)
continue;
if (vis[nx][ny][nz] == 1 || a[nz][ny][nx] == 1)
continue;
que.push(node(nz, ny, nx, s + 1));
vis[nx][ny][nz] = 1;
}
que.pop();
}
if (flag)cout << "Trapped!" << endl;
}
int main() {
char ch;
//input data
while (1) {
cin >> ceng >> chang >> kuan;
if (ceng == 0 && chang == 0 && kuan == 0) break;
for (int i = 1; i <= ceng; i++) { //输入层 长 宽
for (int j = 1; j <= chang; j++) {
string s;
cin >> s;
for (int k = 1; k <= kuan; k++) {
ch = s[k - 1];
if (ch == '.')a[i][j][k] = 0; //i--层 j--长 k--宽
if (ch == '#')a[i][j][k] = 1;
if (ch == 'S')p1 = node(i, j, k, 0); //层--z 长--y 宽--x
if (ch == 'E') {
p2 = node(i, j, k, 0);
a[i][j][k] = 0;
}
}
}
}
bfs();
}
return 0;
}
1249:Lake Counting
【题目描述】
题意:有一块N×M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?
【题目分析】
遍历所有节点,当无标识且不为零,进行深度优先搜索
深搜函数创建队列,对每个满足要求的节点(没有超过边界,无标识,为W)的加入队列,并进行标识
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int n, m;
bool a[115][115];
bool vis[115][115];
int _next[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
void bfs(int x, int y) {
queue<pair<int, int>>que;
que.push(make_pair(x, y));
vis[x][y] = 1;
while (!que.empty()) {
int px = que.front().first;
int py = que.front().second;
for (int i = 0; i < 8; i++) {
int nx = px + _next[i][0];
int ny = py + _next[i][1];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && vis[nx][ny] == 0 && a[nx][ny] == 1) {
vis[nx][ny] = 1;
que.push(make_pair(nx, ny));
}
}
que.pop();
}
}
int main() {
//input data
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
char ch;
cin >> ch;
if (ch == 'W') a[i][j] = 1;
else a[i][j] = 0;
}
}
int _count = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (vis[i][j] == 0 && a[i][j]) {
_count++;
bfs(i, j);
}
}
}
cout << _count << endl;
return 0;
}
1250:The Castle
【题目描述】
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int m, n;
int a[55][55];
int vis[55][55];
int _count = 0, maxa = 0;
int _next[4][2] = {{0, -1}, //无西墙
{-1, 0}, //无北墙
{0, 1}, //无东墙
{1, 0}}; //无南墙
int bfs(int x, int y) { //行是x 列是y
int area = 0;
queue<pair<int, int>>que;
que.push(make_pair(x, y));
vis[x][y] = 1;
while (!que.empty()) {
int px = que.front().first;
int py = que.front().second;
area++;
int qi = a[px][py];
for (int i = 0; i < 4; i++) {
if (!((qi >> i) & 1)) {
int nx = px + _next[i][0];
int ny = py + _next[i][1];
if (vis[nx][ny] == 0) {
vis[nx][ny] = 1;
que.push(make_pair(nx, ny));
}
}
}
que.pop();
}
return area;
}
int main() {
//input data
cin >> m >> n;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (vis[i][j] == 0) {
_count++;
maxa = max(maxa, bfs(i, j));
}
}
}
cout << _count << endl;
cout << maxa << endl;
return 0;
}
1251:仙岛求药
【题目描述】
少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。
下图 显示了一个迷阵的样例及李逍遥找到仙药的路线。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int r, c;
bool a[25][25];
bool vis[25][25];
struct node {
int x;
int y;
int step;
node() {};
node(int _x, int _y, int _step): x(_x), y(_y), step(_step) {};
} p1, p2;
int _next[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
void bfs() {
memset(vis, 0, sizeof(vis));
queue<node> que;
que.push(p1);
int x = p1.x;
int y = p1.y;
vis[x][y] = 1;
bool flag = 1;
while (!que.empty()) {
x = que.front().x;
y = que.front().y;
int s = que.front().step;
if (x == p2.x && y == p2.y) {
cout << s << endl;
flag = 0;
break;
}
for (int i = 0; i < 4; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
if (nx >= 0 && ny >= 0 && nx < r && ny < c && vis[nx][ny] == 0 && a[nx][ny] == 0) {
vis[nx][ny] = 1;
que.push(node(nx, ny, s + 1));
}
}
que.pop();
}
if (flag) cout << -1 << endl;
}
int main() {
//input data
while (cin >> r >> c, !(r == 0 && c == 0)) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
char ch;
cin >> ch;
if (ch == '.') a[i][j] = 0;
if (ch == '#') a[i][j] = 1;
if (ch == '@') p1 = node(i, j, 0);
if (ch == '*') {
p2 = node(i, j, 0);
a[i][j] = 0;
}
}
}
bfs();
}
return 0;
}
1252:走迷宫
【题目描述】
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int r, c;
bool _map[45][45];
bool vis[45][45];
struct node {
int x;
int y;
int step;
node() {};
node(int _x, int _y, int _step): x(_x), y(_y), step(_step) {};
};
int _next[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
queue<node> que;
void bfs() {
que.push(node(0, 0, 1));
vis[0][0] = 1;
while (!que.empty()) {
int x = que.front().x;
int y = que.front().y;
if (x == r-1 && y == c-1) {
cout << que.front().step;
break;
}
for (int i = 0; i < 4; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
if (nx >= 0 && ny >= 0 && nx < r && ny < c && vis[nx][ny] == 0 && _map[nx][ny] == 0) {
que.push(node(nx, ny, que.front().step + 1));
vis[nx][ny] = 1;
}
}
que.pop();
}
}
int main() {
//input data
cin >> r >> c;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
char ch;
cin >> ch;
if (ch == '#')
_map[i][j] = 1;
else
_map[i][j] = 0;
}
}
bfs();
return 0;
}
1253:抓住那头牛
【题目描述】
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0≤N≤100000),牛位于点K(0≤K≤100000)。农夫有两种移动方式:
1、从X移动到X−1或X+1,每次移动花费一分钟
2、从X移动到2×X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int n, k;
bool vis[100001];
queue<pair<int, int>>que;
int main() {
//input data
cin >> n >> k;
que.push(make_pair(n, 0));
vis[n] = 1;
while (!que.empty()) {
int f = que.front().first;
int s = que.front().second;
if (f == k) {
cout << s;
break;
}
if (f + 1 <= 100000 && vis[f + 1] == 0 ) {
que.push(make_pair(f + 1, s + 1));
vis[f + 1] = 1;
}
if (f - 1 >= 0 && vis[f - 1] == 0) {
que.push(make_pair(f - 1, s + 1));
vis[f - 1] = 1;
}
if (f * 2 <= 100000 && vis[f * 2] == 0 ) {
que.push(make_pair(f * 2, s + 1));
vis[f * 2] = 1;
}
que.pop();
}
return 0;
}
1254:走出迷宫
【题目描述】
当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。
假设你已经得到了一个n×m的迷宫的图纸,请你找出从起点到出口的最短路。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
struct node {
int x;
int y;
int step;
node() {};
node(int _x, int _y, int _step): x(_x), y(_y), step(_step) {};
} p1, p2;
int a[205][205];
int vis[205][205];
int _next[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int r, c;
void bfs() {
queue<node> que;
memset(vis, 0, sizeof(vis));
que.push(p1);
vis[p1.x][p1.y] = 1;
bool flag = 1;
while (!que.empty()) {
int x = que.front().x;
int y = que.front().y;
if (x == p2.x && y == p2.y) {
cout << que.front().step << endl;
flag = 0;
break;
}
for (int i = 0; i < 4; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
if (nx >= 0 && ny >= 0 && nx < r && ny < c && vis[nx][ny] == 0 && a[nx][ny] == 0) {
que.push(node(nx, ny, que.front().step + 1));
vis[nx][ny] = 1;
}
}
que.pop();
}
if (flag) cout << "oop!" << endl;
}
int main() {
//input data
cin >> r >> c;
char ch;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> ch;
if (ch == '.')
a[i][j] = 0;
if (ch == '#')
a[i][j] = 1;
if (ch == 'S')
p1 = node(i, j, 0);
if (ch == 'T') {
p2 = node(i, j, 0);
a[i][j] = 0;
}
}
}
bfs();
return 0;
}
1255:迷宫问题
【题目描述】
定义一个二维数组:
int maze[5][5] = { 0,1,0,0,0, 0,1,0,1,0, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,1,0, };
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5;
struct node {
int x;
int y;
node() {};
node(int _x, int _y): x(_x), y(_y) {};
} rec[maxn][maxn];
int a[maxn][maxn];
int _next[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
queue<node> que;
stack<node> st;
bool vis[maxn][maxn];
void bfs() {
que.push(node(4, 4));
vis[4][4] = 1;
while (!que.empty()) {
int x = que.front().x;
int y = que.front().y;
if (x == 0 && y == 0) break;
for (int i = 0; i < 4; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
if (nx >= 0 && ny >= 0 && nx < 5 && ny < 5 && a[nx][ny] == 0 && vis[nx][ny] == 0) {
que.push(node(nx, ny));
rec[nx][ny] = node(x, y);
vis[nx][ny] = 1;
}
}
que.pop();
}
}
int main() {
//input data
for (int i = 0; i < maxn; i++) {
for (int j = 0; j < maxn; j++) {
cin >> a[i][j];
}
}
bfs();
int x = 0, y = 0;
while (x + y != 8) {
printf("(%d, %d)\n", x, y);
int nx = rec[x][y].x;
int ny = rec[x][y].y;
x = nx, y = ny;
}
printf("(%d, %d)\n", x, y);
return 0;
}
1256:献给阿尔吉侬的花束
【题目描述】
阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。
迷宫用一个R×C的字符矩阵来表示。字符S表示阿尔吉侬所在的位置,字符E表示奶酪所在的位置,字符#表示墙壁,字符.表示可以通行。阿尔吉侬在1个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
struct node {
int x;
int y;
int step;
node() {};
node(int _x, int _y, int _step): x(_x), y(_y), step(_step) {};
} p1, p2;
int a[205][205];
int vis[205][205];
int _next[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int r, c;
void bfs() {
queue<node> que;
memset(vis, 0, sizeof(vis));
que.push(p1);
vis[p1.x][p1.y] = 1;
bool flag = 1;
while (!que.empty()) {
int x = que.front().x;
int y = que.front().y;
if (x == p2.x && y == p2.y) {
cout << que.front().step << endl;
flag = 0;
break;
}
for (int i = 0; i < 4; i++) {
int nx = x + _next[i][0];
int ny = y + _next[i][1];
if (nx >= 0 && ny >= 0 && nx < r && ny < c && vis[nx][ny] == 0 && a[nx][ny] == 0) {
que.push(node(nx, ny, que.front().step + 1));
vis[nx][ny] = 1;
}
}
que.pop();
}
if (flag) cout << "oop!" << endl;
}
int main() {
//input data
int T;
cin >> T;
while (T--) {
cin >> r >> c;
char ch;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> ch;
if (ch == '.')
a[i][j] = 0;
if (ch == '#')
a[i][j] = 1;
if (ch == 'S')
p1 = node(i, j, 0);
if (ch == 'E') {
p2 = node(i, j, 0);
a[i][j] = 0;
}
}
}
bfs();
}
return 0;
}
1257:Knight Moves
【题目描述】
输入n代表有个n×n的棋盘,输入开始位置的坐标和结束位置的坐标,问一个骑士朝棋盘的八个方向走马字步,从开始坐标到结束坐标可以经过多少步。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int L;
struct node {
int x;
int y;
int step;
node() {};
node(int _x, int _y, int _step): x(_x), y(_y), step(_step) {};
} p1, p2;
int vis[305][305];
queue<node>que;
int _next[8][2] = {{1, 2}, {1, -2}, {2, 1}, {2, -1},
{-1, 2}, {-1, -2}, {-2, 1}, {-2, -1}
};
int main() {
//input data
int x, y;
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> L;
memset(vis, 0, sizeof(vis));
que = queue<node>();
cin >> x >> y;
p1 = node(x, y, 0);
cin >> x >> y;
p2 = node(x, y, 0);
que.push(p1);
vis[p1.x][p1.y] = 1;
while (!que.empty()) {
if (que.front().x == p2.x && que.front().y == p2.y) {
cout << que.front().step << endl;
break;
}
for (int i = 0; i < 8; i++) {
x = que.front().x + _next[i][0];
y = que.front().y + _next[i][1];
if (x >= 0 && y >= 0 && x < L && y < L && vis[x][y] == 0) {
vis[x][y] = 1;
que.push(node(x, y, que.front().step + 1));
}
}
que.pop();
}
}
return 0;
}