Topic 1 simple search

Posted by todayme on Mon, 10 Jan 2022 12:48:12 +0100

50: Naruto and Sasuke BFS
Description
Sasuke was lured away by big snake pill. How long can Naruto catch up with him?
A map (in the form of a two-dimensional matrix) and the locations of Sasuke and Naruto are known. You can go to every position on the map, but there are big snake pill's men in some positions. You need to defeat big snake pill's men before you can get to these positions. Naruto has a certain number of chakras. Chakras of each unit can defeat a subordinate of big snake pill. Suppose Naruto can move up, down, left and right. It takes 1 unit time to move a distance. It doesn't take time to defeat the men of big snake pill. If Naruto chakra is exhausted, he can only go to the position without big snake pill, and can no longer move to the position with big snake pill. Sasuke did not move during this period, nor did the men of big snake pill. How long does it take Naruto to catch up with Sasuke?

Input
The first line of input contains three integers: m, N, t. Represents the map of row m and column n and the initial chakra number T of Naruto. 0 < M,N < 200，0 ≤ T < 10. Followed by the map in row m and column n, where @ represents Naruto and + represents Sasuke* Represents the channel and # represents the men of big snake pill.
Output
The output contains an integer R, which represents the minimum time it takes for Naruto to catch up with Sasuke. If Naruto cannot catch up with Sasuke, output - 1.

Sample Input
Sample input 1

4 4 1
#@##
**##
###+
****
1
2
3
4
5
Sample input 2

4 4 2
#@##
**##
###+
****
1
2
3
4
5
Sample Output
Sample output 1

6
1
Sample output 2

4
1
Topic analysis
Because this problem is to find the shortest path (time), we still choose breadth first search. However, the difference is that in addition to coordinates (x,y) and time (tot), the current number of chakras (T) is also increased in the structure of the queue. Now let's start the analysis process——
1. Define variables to avoid repeating the path (awl)
2. Input is the same as that of other maze topics, and the starting point needs to be saved
4. Traverse 4 directions
5. Judge the boundary and repetition. This is a difficult problem - for the common maze problem, we will use the two-dimensional bool array to judge the repetition, or even directly change the original map - but this problem will have a BUG and give a data (the default priority is to walk down, and the coordinates start from (0,0)):

5 5 2
@#***
####*
#**#*
#****
+####

When you first see the shortest time, you must think of BFS, but this problem is different from ordinary BFS. Ordinary BFS marks the visited points and can find the shortest path. However, the points that have been accessed by 2D markers can no longer be accessed here, because the marked points can no longer be accessed, and here is likely to be accessed again.

3  6    1
@#****
*#*###
***##+

Taking this example as an example, first remove the factor of chakra and regard it as an ordinary wide search. We know that in order to find the shortest path, wide search will mark which points to visit

(1，1)——>(1，2)——>(1，3). . . I will mark (1, 3), but I find it impossible to go this way because of the lack of chakra and other factors.

So another correct path (1,1) - > (2,1) - > (3,1) - > (3,2) - > (3,3) - > (2,3) - > (1,3) also comes to (1,3). At this time (1,3) is also marked, can no longer be accessed, and - 1 is output

How to solve the above problems:

1. Can you remove the st tag array without using it?

A: No, it will exceed the memory

This is a super memory error code, still using a two-dimensional tag array

#include <iostream>
#include <cstring>
#include <cmath>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=205;
int px,py;
int dx={-1,0,1,0};
int dy={0,1,0,-1};
char map[N][N];
int dis[N][N];  //The marking function of dis is removed
struct node
{
int x,y;
int co;
}q[N*N*N];
int n,m,t;
int bfs(int x,int y)
{
int hh=0,tt=-1;
//memset(dis,-1,sizeof dis);
dis[x][y]=0;
q[++tt]={x,y,t};

while(hh<=tt)
{

struct node t=q[hh++];
if(map[t.x][t.y]=='+')
{
return dis[t.x][t.y];
}

for(int i=0;i<4;i++)
{
int xx=t.x+dx[i];
int yy=t.y+dy[i];
if(xx>=0&&xx<m&&yy>=0&&yy<n)//Unmarked array duplicate check
{

if(map[xx][yy]=='#')
{
if(t.co-1>=0)
{
dis[xx][yy]=dis[t.x][t.y]+1;
q[++tt]={xx,yy,t.co-1};
//	cout<<"xx is "<<xx<<" yy is "<<yy<<endl;
}
else continue;
}
else
{
dis[xx][yy]=dis[t.x][t.y]+1;
q[++tt]={xx,yy,t.co};
//	cout<<"xx is "<<xx<<" yy is "<<yy<<endl;
}
}
}
}

return -1;
}
int main()
{
while(cin>>m>>n>>t)
{
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
cin>>map[i][j];
if(map[i][j]=='@')
{
px=i;
py=j;
}
}

cout<<bfs(px,py)<<endl;
}

return 0;
}

2. What is the correct approach?

A three-dimensional array is used. The first two dimensions correspond to the normal coordinates, and the last one is used to record the remaining number of chakras at this point. In this way, if they pass through a point repeatedly, as long as their remaining number of chakras is different, they are independent of each other, just like the examples of the two paths mentioned earlier

#include <iostream>
#include <cstring>
#include <cmath>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=205;
int px,py;
int dx={-1,0,1,0};
int dy={0,1,0,-1};
char map[N][N];
bool st[N][N][N];   //Define triple Tags
struct node
{
int x,y;
int co;
int step;
}q[N*N];
int n,m,t;
int bfs(int x,int y)
{
memset(st,false,sizeof st);
int hh=0,tt=-1;
st[x][y]=true;
q[++tt]={x,y,t,0};

while(hh<=tt)
{

struct node t=q[hh++];
if(map[t.x][t.y]=='+')
{
return t.step;
}

for(int i=0;i<4;i++)
{
int xx=t.x+dx[i];
int yy=t.y+dy[i];
if(xx>=0&&xx<m&&yy>=0&&yy<n)
{

if(map[xx][yy]=='#')
{
if(t.co-1>=0)
{
if(!st[xx][yy][t.co-1])
{
q[++tt]={xx,yy,t.co-1,t.step+1};
//	cout<<"xx is "<<xx<<" yy is "<<yy<<endl;
st[xx][yy][t.co-1]=true;
}
}
else continue;
}
else
{
if(!st[xx][yy][t.co])
{
st[xx][yy][t.co]=true;
q[++tt]={xx,yy,t.co,t.step+1};
//	cout<<"xx is "<<xx<<" yy is "<<yy<<endl;
}
}
}
}
}

return -1;
}
int main()
{
while(cin>>m>>n>>t)
{
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
cin>>map[i][j];
if(map[i][j]=='@')
{
px=i;
py=j;
}
}

cout<<bfs(px,py)<<endl;
}

return 0;
}

Topics: C++