十分复杂的BFS
Posted virtualtan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十分复杂的BFS相关的知识,希望对你有一定的参考价值。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
int n,m;
int arr[50+9][50+9];//坐标的
bool vis[25000];//标记访问过的
int x1,x2,y1,y2;
char reword;
int to;
int dx[5] = {0,1,-1,0,0};//上下左右 1234
int dy[5] = {0,0,0,-1,1};//刚好对应 fitreword() 中的方向
//dx[i]表方向i(编号)的x情况 //dy[i]表方向i(编号)的y情况
int ft[5] = {0,1,4,2,3}//因为我们遍历是顺时针的,而我们定义了↑为1,↓为2,←为3,→为4
//这个ft[i] 的作用是把顺时针for的1234 转换为我们定义了的方向
int fft[5] = {0,1,3,4,2};// fft[i]表示方向i在ft[]数组中的下标
int fft[5] = {0,} ;
int abc[5]={0,1,2,1,0};//abc[5]表示转到[顺时针转i次到达的那个方向]的最短次数
struct node {
int x,y,dis,reword;
//坐标,已花时间,朝向;
};
queue <node> q;
void fitreword() {
switch(reword) {
case ‘N‘ : to = 1;break;
case ‘S‘ : to = 2;break;
case ‘W‘ : to = 3;break;
case ‘E‘ : to = 4;break;//北南西东 1234
}
}
void bds() {
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
cin >> reword;
fitreword();//转换方向 此时方向 to 表示的就是方向的代号
node e1,e2;
e1.x = x1,e1.y = y1, e1.dis = 0, e1.reword = to;
q.push(e1);
int zhuan,fangx;
//zhuan [顺时针转i下的那个方向]的最短旋转次数
//fangx 旋转完了以后方向的编号fangx
while(!q.empty() ) {
e2 = q.front() ;
q.pop() ;
for(int i = 1; i <= 4; i++) {//顺时针旋转的四个方向
zhuan = abc[i];
fangx = fft[e2.reword ] + i;//因为从node里取出来的reword是方向的代号,这里是把它转换成下标
if(fangx == 5) fangx = 1;
if(fangx == 6) fangx = 2;
if(fangx == 7) fangx = 3;
if(fangx == 8) fangx = 4;
fangx = ft[fangx];//至此,总算把fangx转换为旋转后的方向编号了...
}
}
}
int main() {
bool tmp;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> tmp;
if(tmp) {//如果是障碍//用于将格子转化成坐标的图(机器人有体积,不好判断)
arr[i][j] = 1;//因为输入的是格子,他四个顶点都不能走
arr[i][j+1] = 1;//相当于输入的是这个格子左上的点(仔细看看就知道)
arr[i+1][j] = 1;
arr[i+1][j+1] = 1;
}
}
}
/* for(int i = 1; i <= n; i++) {//机器人是有体积的,所以最外层不能走
arr[n][i] = 1;
arr[i][m] = 1;
}*/
bfs();
return 0;
}
错误代码:
#include<cstdio>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
int n,m;
int arr[50+9][50+9];
bool vis[50+9][50+9];
struct node{
int x,y,dis,dir;
node(int x = 0, int y = 0, int dis = 0, int dir = 0) : x(x), y(y), dis(dis), dir(dir) {} //构造函数
};
queue <node> q;//亲爱的队列
const char* dirs = "NESW";//这里方向是顺时针,所以下面的顺时针转动时就直接(dir + 1) 再 % 4
// 如果是逆时针转动,就 + 3 之后再 % 4
const char* turns = "FLR";
//四个方向和三种“转弯”方式,提供相应的转换函数
int dir_id(char dir) { return strchr(dirs,dir) - dirs;} //strchr(s,c) 可以查找字符串s中首次出现字符c的位置(注意减去s)。
int turn_id(char turn){ return strchr(turns,turn) - turns;}
//接下来是“行走”函数:根据当前状态 和 "朝向",返回行走后的状态(有x,有y,有dir)
const int dx[] = {-1,0,1,0};//北东南西 一一对应
const int dy[] = {0,1,0,-1};
node walk (const node& u, int turn,int cnt) {
int dir = u.dir ;//直走
if(turn == 1) dir = (dir + 3) % 4;//“1”在turns 里面表示向左转,那么这里就逆时针转动
//因为这样转动所花的时间最少
else if(turn == 2) dir = (dir + 1) % 4;//同理,顺时针
return node(u.x + dx[dir]*cnt, u.y + dy[dir]*cnt, dir) ;//因为有构造函数,可以这样直接返回
}
void print_ans(node u) {
printf("%d",u.dis );
}
void bfs() {//成败在此一举
int x1,y1,x2,y2;//起点&终点
char reword;
cin >> x1 >> y1 >> x2 >> y2 >> reword;
node u,e1,e2,e3;
u.x = x1, u.y = y1, u.dir = turn_id(reword), u.dis = 0;
q.push(u);
vis[u.x ][u.y ] = 1;//标记为已访问
while(!q.empty() ) {
u = q.front() ;
q.pop() ;
if(u.x = x2 && u.y == y2) {
print_ans(u);
return ;
}
for(int i = 0; i <= 3; i++) {//遍历三个朝向
e1 = walk(u, i, 1);//行走一步之后
/*ken*/ if(e1.x>=1 && e1.x<=n && e1.y<=m && e1.y>=1 && arr[e1.x ][e1.y ]==0 && vis[e1.x ][e1.y ] == 1)
//不是障碍 并且没有走过
{
e1.dis = u.dis + 1;
q.push(e1);
}
e2 = walk(u, i, 2);//行走2步之后
/*ken*/ if(e2.x>=1 && e2.x<=n && e2.y<=m && e2.y>=1 && arr[e2.x ][e2.y ]==0 && vis[e2.x ][e2.y ] == 1)
{
e2.dis = u.dis + 1;
q.push(e2);
}
e3 = walk(u, i, 3);//行走3步之后
/*ken*/ if(e3.x>=1 && e3.x<=n && e3.y<=m && e3.y>=1 && arr[e3.x ][e3.y ]==0 && vis[e3.x ][e3.y ] == 1)
{
e3.dis = u.dis + 1;
q.push(e3);
}
}
}
printf("-1");
}
int main() {
bool tmp;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> tmp;
if(tmp) {//如果是障碍//用于将格子转化成坐标的图(机器人有体积,不好判断)
arr[i][j] = 1;//因为输入的是格子,他四个顶点都不能走
arr[i][j+1] = 1;//相当于输入的是这个格子左上的点(仔细看看就知道)
arr[i+1][j] = 1;
arr[i+1][j+1] = 1;
}
}
}
/* for(int i = 1; i <= n; i++) {//机器人是有体积的,所以最外层不能走
arr[n][i] = 1;
arr[i][m] = 1;
}*/
bfs();
return 0;
}
https://www.luogu.org/problemnew/show/UVA816
#include<cstdio>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
int n,m;
char reword;
bool vis[50+9][50+9][5];
bool has_edge[50+9][50+9][5][5];
//has_edge【x】【y】【dir】【turn】表示在(x,y,dir)/*这就是状态*/ 是否能够沿着转弯方式turn 走
struct node{
int x,y,dis,dir;
node(int x = 0, int y = 0, int dis = 0, int dir = 0) : x(x), y(y), dis(dis), dir(dir) {} //构造函数
};
queue <node> q;//亲爱的队列
const char* dirs = "NESW";//这里方向是顺时针,所以下面的顺时针转动时就直接(dir + 1) 再 % 4
// 如果是逆时针转动,就 + 3 之后再 % 4
const char* turns = "FLR";
//四个方向和三种“转弯”方式,提供相应的转换函数
int dir_id(char dir) { return strchr(dirs,dir) - dirs;} //strchr(s,c) 可以查找字符串s中首次出现字符c的位置(注意减去s)。
int turn_id(char turn){ return strchr(turns,turn) - turns;}
//接下来是“行走”函数:根据当前状态 和 "朝向",返回行走后的状态(有x,有y,有dir)
const int dx[] = {-1,0,1,0};//北东南西 一一对应
const int dy[] = {0,1,0,-1};
node walk (const node& u, int turn,int cnt) {
int dir = u.dir ;//直走
if(turn == 1) dir = (dir + 3) % 4;//“1”在turns 里面表示向左转,那么这里就逆时针转动
else if(turn == 2) dir = (dir + 1) % 4;//同理,顺时针
return node(u.x + dx[dir]*cnt, u.y + dy[dir]*cnt, dir) ;//因为有构造函数,可以这样直接返回
}
void print_ans(node u) {
}
void bfs() {//成败在此一举
node u,e1,e2,e3;
}
int main() {
string tmp;
char tmp2[99];
int x0,x1,x2,y0,y1,y2,dir;
int x3,y3;
while(1) {
cin >> tmp;
if(tmp == "END") return 0;
cout << tmp << endl;
cin >> x0 >> y0 >> reword >> x2 >> y2;
dir = dir_id(reword);
x1 = x0 + dx[dir];
y1 = y0 + dy[dir];//起点是走之后的点
memset(has_edge, 0, sizeof(has_edge));
whlie(1) {
scanf("%d",&x3);//分开输入,判断是否为结束标志“0”;
if(x3 == 0) break;
scanf("%d",&y3);
whlie(scanf("%s",s) && s[0] != ‘*‘) {
for(int i = 1; i < strlen(s); i++) {//存has_edge (从1开始)
has_edge[x3][y3][dir_id(s[0])][turn_id(s[i])] =
}
}
}
}
return 0;
}
以上是关于十分复杂的BFS的主要内容,如果未能解决你的问题,请参考以下文章