BFS - Marching Legion - ab Knight

Marching Legion

时间限制: 1 Sec 内存限制: 128 MB
题目描述
There’s a rebellion in Antioch! Caesar is preparing to dispatch an entire legion of his best troops to quell the rebellion, but before he does, he wants to make certain the legion will make it to Antioch.
Along the way, there are mountains, rivers, seas, and mythical monsters, each of which the legion cannot pass through. Given a map a legion must travel through, find out if the legion can reach Antioch from Rome.
输入
The first line of the input will be a single integer, n ≤ 1, 000. There will be n test cases that follow.
Input will begin with two integers, 0 < h, w < 100, indicating the height and width of the map, respectively. h lines with w characters each will follow. An “X” on the map represents an impassable obstacle while an “O” represents traversable terrain. Note that legions, moving in square formations, can only move up, down, left, and right; legions can never travel diagonally. “R” represents Rome, the starting point of the legion, and “A” represents Antioch, the destination point for the legion
输出
Output “March onward!” if the legion can reach Antioch from Rome, “Stay home!” otherwise. Each output should be line separated.
样例输入
3
6 6
XXXXOA
XOXXOX
XOXXOX
XOOOOX
XOXXXX
XROOOX
4 4
XXOA
XOOX
XOXX
XRXO
2 2
XA
RX
样例输出
March onward!
March onward!
Stay home!

题意:给你一个n*m的棋盘,A位置为出发点,R 位置为目标点,O位置为通路,X位置不可走。询问是否可以从A位置走到R位置.如果可以输出“March onward!”,否则输出“Stay home!”;

第一思路DFS:
Code:

/*
Author:MYS
Date:2021.4.11
*/
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int N = 1e3+10;
const int mod = 1e9+7;
#define pp putchar('\n')
inline int read() {
    int sign=1,num=0;
    char ch = getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-') sign=-1;
        ch = getchar();
    }
    while(ch>='0'&&ch<='9') {
        num=num*10+ch-'0';
        ch = getchar();
    }
    return sign*num;
}
char a[1010][1010];
int t,n,m;
int dir[5][5]= {{1,0},{-1,0},{0,1},{0,-1}};
bool vis[1010][1010];
bool judge(int dx,int dy) {
    if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&(a[dx][dy]=='O'||a[dx][dy]=='R')) {
        return 1;
    }
    return 0;
}
bool f;
void dfs(int x,int y) {
    if(f) return;
    //cout<<x<<" "<<y<<" "<<a[x][y]<<endl;
    if(a[x][y]=='R') {
    f=1;return;
    }
    vis[x][y] = 1;
    int j=0;
    for(int i=0; i<4; i++) {
        int dx = x+dir[i][0];
        int dy = y+dir[i][1];
        if(judge(dx,dy)&&!vis[dx][dy]) {
            dfs(dx,dy);
            vis[dx][dy] = 0;//回溯
        }
    }
}
int main() {
    scanf("%d",&t);
    while(t--) {
        f=0;
        scanf("%d%d",&n,&m);
        memset(vis,0,sizeof(vis));
        int si,sj;
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=m; j++) {
                cin>>a[i][j];
                if(a[i][j]=='A') si=i,sj=j;
            }
        }
        dfs(si,sj);
        if(f) printf("March onward!");
        else printf("Stay home!");
        putchar('\n');
  
    }
  
    return 0;
}

结果TEL


换BFS:
Code:

/*
Author:MYS
Date:2021.4.11
*/
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int N = 1e3+10;
const int mod = 1e9+7;
#define pp putchar('\n')
inline int read() {
	int sign=1,num=0;
	char ch = getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') sign=-1;
		ch = getchar();
	}
	while(ch>='0'&&ch<='9') {
		num=num*10+ch-'0';
		ch = getchar();
	}
	return sign*num;
}
struct node {
	int x,y;
};
int m,n;
int t,sx,sy,ex,ey;
char ch[110][110];
int dir[5][5]= {{1,0},{-1,0},{0,1},{0,-1}};

queue<node> q;
bool judge(int xx,int yy) {
	if(xx>=1&&xx<=m&&yy>=1&&yy<=n&&(ch[xx][yy]=='O'||ch[xx][yy]=='R')) return 1;
	return 0;
}
int bfs() {
	while(q.size()) q.pop();
	q.push({sx,sy});
	while(q.size()) {
		int nx = q.front().x;
		int ny = q.front().y;
		//cout<<nx<<" "<<ny<<endl;
		q.pop();
		if(nx==ex&&ny==ey) {
			return 1;  //找到即立即返回
		}
		for(int i=0; i<4; i++) {
			int dx = nx+dir[i][0];
			int dy = ny+dir[i][1];
			if(judge(dx,dy)) {  //符合条件就入队
				ch[dx][dy] = 'X';
				q.push({dx,dy});
			}
		}
	}

	return 0;
}
int main() {
	cin>>t;
	while(t--) {
		sx = sy = ex = ey = 0;
		cin>>m>>n;
		for(int i=1; i<=m; i++) {
			for(int j=1; j<=n; j++) {
				cin>>ch[i][j];
				if(ch[i][j]=='A') {
					sx = i;
					sy = j;
				}
				if(ch[i][j]=='R') {
					ex = i;
					ey = j;
				}
			}
		}
		if(bfs()) puts("March onward!");
		else puts("Stay home!");
	}

	return 0;
}

结果AC


为什么DFS会T泥?有一说一可能是有数据会卡你,问了WSQ学姐,学姐说能BFS就先BFS。我们可以相应的输出一下DFS和BFS跑的路径看一下有何不同;
在这里插入图片描述
在这里插入图片描述

  • 我们通过输出路径可以看出来这个DFS是一条路给他跑到底,不撞南墙不回头的那种,这也就是为啥叫他深度优先搜索,如果跑到最后发现这条路不行就再给他回溯回去。
  • 而BFS不一样,如果在一个地方出现了岔路,就如上面样例的(4,2)处,他是分路同时走,也就是当(4,2)这个节点出现了两个分节点时,他是两个分节点同时遍历的,这也就是为啥叫他广度优先搜索,而不是像个蛮牛一样一路顶到底。

ab Knight

题目描述
In chess, a knight is the only piece that can “jump” over pieces. Namely, a typical knight can move 1 square up, down, left or right, followed by 2 squares in a perpendicular direction. Thus, if a knight is at square (x, y), after its jump it can end up at one of these eight positions:
(x ± 1, y ± 2), (x ± 2, y ± 1), provided that they are in bounds and there isn’t a piece on the destination square.
Now, consider a modified knight called an ab knight, where a and b are both positive integers, not necessarily distinct. From square (x, y), the eight squares the ab knight can reach on a single jump are (x ± a, y ± b), (x ± b, y ± a), provided that they are in bounds.
For the purposes of this problem, we’ll assume that there are no pieces on the board except for the original ab knight. Our goal will be to calculate the fewest number of jumps necessary for the knight to reach each of the other squares on the board.
The Problem
Given the size of a chess board, the values of a and b for the ab knight, and the initial position of
the ab knight, determine the fewest number of moves necessary for the ab knight to reach each of
the squares on the board, or determine that some squares aren’t reachable.
输入
The first line of input will contain a single positive integer, n (n ≤ 20), representing the number of input cases to process. The input cases follow, each taking up three lines. The first line of each input case contains two space separated positive integers, r (3 ≤ r ≤ 100) and c (3 ≤ c ≤ 100), representing the number of rows and columns on the chessboard for the input case. The second line of each input case contains two space separated positive integers, a (a ≤ min(r, c)) and b (b ≤ min(r, c)), representing the values of a and b for the ab knight for the input case. The third line of each input case contains two space separated positive integers, x (x ≤ r) and y (y ≤ c), representing the row and column of the initial location of the ab knight. Assume that the top left hand corner of the board is square is row 1, column 1, the bottom left hand corner of the board is square row r, column 1, the top right hand corner of the board is square row 1, column c, and the bottom right corner of the board is square row r, column c.
输出
For each case, output r lines of c space separated integers, where the jth value on the ith line represent the fewest number of jumps necessary for the ab knight to travel from its initial square to row i column j. Remember not to output a space after the last integer on each row. If a square is unreachable by the ab knight, print out -1 instead.
样例输入
2
3 3
1 2
1 1
2 5
1 1
1 2
样例输出
0 3 2
3 -1 1
2 1 4
-1 0 -1 2 -1
1 -1 1 -1 3

题意:
给你一个r*c的棋盘,再给你一个出发点,让你判断是否你能从出发点走到所有位置,走不到的位置输出“-1”,能到达的位置输出最少多少步到达;

Code:

/*
Author:MYS
Date:2021.4.16
*/
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int N = 1e4+10;
const int inf = 0x3f3f3f;
#define pp putchar('\n')
inline int read() {
	int sign=1,num=0;
	char ch = getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') sign=-1;
		ch = getchar();
	}
	while(ch>='0'&&ch<='9') {
		num=num*10+ch-'0';
		ch = getchar();
	}
	return sign*num;
}
int t,r,c;
int a,b,sx,sy;
struct node {
	int x,y;
};
queue<node> q;
bool vis[110][110];
int dis[110][110];
void BFS(int x,int y) {
	int dir[10][10]= {{a,b},{a,-b},{-a,b},{-a,-b},{b,a},{b,-a},{-b,a},{-b,-a}};
	q.push({x,y});
	vis[x][y] = 1;
	dis[x][y] = 0;
	while(!q.empty()) {
		int nx = q.front().x;
		int ny = q.front().y;
		q.pop();
		for(int i=0; i<8; i++) {
			int dx = nx+dir[i][0];
			int dy = ny+dir[i][1];
			if(dx>=1&&dx<=r&&dy>=1&&dy<=c&&!vis[dx][dy]) {
				q.push({dx,dy});
				vis[dx][dy] = 1;
				dis[dx][dy] = dis[nx][ny]+1;
			}
		}
	}
}
int main() {
	cin>>t;
	while(t--) {
		cin>>r>>c;
		cin>>a>>b>>sx>>sy;
		memset(vis,0,sizeof(vis));
		for(int i=1; i<=r; i++)
			for(int j=1; j<=c; j++)
				dis[i][j] = inf;
		BFS(sx,sy);
		for(int i=1; i<=r; i++) {
			for(int j=1; j<=c; j++) {
				if(vis[i][j]) cout<<dis[i][j];
				else cout<<"-1";
				if(j!=c) cout<<" ";
			}
			pp;
		}
	}
	return 0;
}

暂时就酱,如有错误或疑问,还请看官指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值