题目链接:https://ac.nowcoder.com/acm/contest/11253/I
题目:
现有一个 20 * 41 的矩阵 , 第 21 列被阻挡住了,不能走。 现在给你两个人,一个人在 (20,20)的位置,它只能走左半部分的(20 * 20),一个人在(20,1)的位置,它只能走右半部分的位置。左边的人要走到(1,20)的位置, 右边的人要走到(1,22)的位置。
现在对他们两个走的方式进行了限制
以左边人走的方向为基准。
左边人a,右边人b
a往左走, b则往右走。
a往右走,b则往左走。
a往上走,b则往上走。
a往下走,b则往下走。
同时还要注意,此题走的方向要用字典序最小情况:要求(D<L<R<U).
求同时到达指定地点的 最短路径。以左边人为基准的走的方式,然后把走过的路径修改为'A',输出两个数组。
输入:
注意:中间第21列为空格隔开,代表左边不能走到右边,右边不能走到左边。
第一行输出最短步数,
第二行输出走的路径,
第三行输出修改后数组的情况。
思路:
此题是一道bfs的题目,首先存好对应的数组情况,并给它的四周赋值为'#'代表不能过去。
然后设置好四个方向走时对应的数组。以及方向后。进行bfs.
使用bfs由某个点到另一个点的过程中,要判断这个新的点之前是否走过了,使用一个choose[][][][]四维数组标记某个点是否走过,走了了就不用走,直接continue.
同时还要判断是否某个人被挡住了。如果某个人这个点被挡住了而另一个人没被挡住,则这个被挡住的人节点不变,没被挡住的人节点改变。
如果两个人都被挡住了,continue即可。
同时使用一个path[][][][]数组统计其前一个节点的四个坐标。后面修改路径'A'的时候要用。同时输出路径方向的时候要用
最后还有一个数组 f2[][][][]用来统计由前一个点到这个点的放下,是向上,想左,还是向右...
同时由后往前推里出了路径,所以我们用一个栈先把路径存下,然后先进后出,得到的就是从出发点到终点的路径过程。
代码实现:
# include <iostream>
# include <queue>
# include <stack>
using namespace std;
const int N = 25;
char ch1[N][N],ch2[N][N];
bool choose[N][N][N][N]; // 最主要的是这里,标记用一个四维进行标记而不是两维进行标记
// 走的顺序是有规定的,因为D < L < R < U.所以我们要走的时候,应该按照这样的顺序。能先往D就先往D走,以此类推。
int x1[4] = {1,0,0,-1}; // 下,左,右,上
int y1[4] = {0,-1,1,0};
int x2[4] = {1,0,0,-1}; // 下,右,左,上
int y2[4] = {0,1,-1,0};
char f[4] = {'D','L','R','U'};
struct node
{
int lx1,ly1,lx2,ly2; // 两企鹅的坐标
int cnt; // 当前走过的步数
};
struct node path[N][N][N][N]; // path[i][j][k][d] 存的就是走到这个节点的上一个节点
int f2[N][N][N][N]; // f2[i][j][k][d]存的就是上一个节点走到这个节点的方向
queue <node> q;
stack<int> st;
void print(int lx1 ,int ly1 , int lx2 ,int ly2) // 打印路径和修改数组值
{
int tempx1 = lx1, tempy1 = ly1 , tempx2 = lx2 , tempy2 = ly2;
while(tempx1 != 20 || tempy1 != 20 || tempx2 != 20 || tempy2 != 1)
{
ch1[tempx1][tempy1] = 'A';
ch2[tempx2][tempy2] = 'A';
st.push(f2[tempx1][tempy1][tempx2][tempy2]);
struct node temp3 = path[tempx1][tempy1][tempx2][tempy2];
tempx1 = temp3.lx1;
tempy1 = temp3.ly1;
tempx2 = temp3.lx2;
tempy2 = temp3.ly2;
}
while(st.size())
{
printf("%c",f[st.top()]);
st.pop();
}
printf("\n");
ch1[20][20] = 'A';
ch2[20][1] = 'A';
for(int i = 1 ; i <= 20 ; i++)
{
for(int j = 1 ; j <= 20 ; j++)
{
printf("%c",ch1[i][j]);
}
printf(" ");
for(int j = 1 ; j <= 20 ; j++)
{
printf("%c",ch2[i][j]);
}
printf("\n");
}
}
void bfs()
{
q.push({20,20,20,1,0});
while(q.size())
{
struct node t = q.front() ;
q.pop();
int lx1 = t.lx1;
int ly1 = t.ly1;
int lx2 = t.lx2;
int ly2 = t.ly2;
int stp = t.cnt;
if(lx1 == 1 && ly1 == 20 && lx2 == 1 && ly2 == 1) //到达了终点了
{
printf("%d\n",stp);
print(lx1,ly1,lx2,ly2);
return;
}
else
{
for(int i = 0 ; i < 4 ; i++) // 两个企鹅向四个方向出发
{
int newlx1 = lx1 + x1[i];
int newly1 = ly1 + y1[i];
int newlx2 = lx2 + x2[i];
int newly2 = ly2 + y2[i];
if(ch1[newlx1][newly1] == '#' && ch2[newlx2][newly2] == '#')
{
continue;
}
if(ch1[newlx1][newly1] == '#' && ch2[newlx2][newly2] != '#')
{
if(choose[lx1][ly1][newlx2][newly2]) // 如果已经走过了的话
{
continue;
}
choose[lx1][ly1][newlx2][newly2] = true;
path[lx1][ly1][newlx2][newly2] = {lx1,ly1,lx2,ly2,stp};
f2[lx1][ly1][newlx2][newly2] = i;
q.push({lx1,ly1,newlx2,newly2,stp + 1});
}
else if(ch1[newlx1][newly1] != '#' && ch2[newlx2][newly2] == '#')
{
if(choose[newlx1][newly1][lx2][ly2])
{
continue;
}
choose[newlx1][newly1][lx2][ly2] = true;
path[newlx1][newly1][lx2][ly2] = {lx1,ly1,lx2,ly2,stp};
f2[newlx1][newly1][lx2][ly2] = i;
q.push({newlx1,newly1,lx2,ly2,stp + 1});
}
else
{
if(choose[newlx1][newly1][newlx2][newly2])
{
continue;
}
choose[newlx1][newly1][newlx2][newly2] = true;
path[newlx1][newly1][newlx2][newly2] = {lx1,ly1,lx2,ly2,stp};
f2[newlx1][newly1][newlx2][newly2] = i;
q.push({newlx1,newly1,newlx2,newly2,stp + 1});
}
}
}
}
}
int main()
{
for(int i = 0 ; i < 25 ; i++)
{
ch1[0][i] = '#';
ch2[0][i] = '#';
ch1[i][0] = '#';
ch2[i][0] = '#';
ch1[21][i] = '#';
ch2[21][i] = '#';
ch1[i][21] = '#';
ch2[i][21] = '#';
}
for(int i = 1 ; i <= 20 ; i++)
{
for(int j = 1 ; j <= 20 ; j++)
{
cin >> ch1[i][j];
}
for(int j = 1 ; j <= 20 ; j++)
{
cin >> ch2[i][j];
}
}
choose[20][20][20][1] = true;
bfs();
return 0;
}