PTA: save 007 (upgraded) (30 points)

Keywords: Algorithm data structure dfs bfs

Title:  

In the old movie "Live and Let Die", there is a plot in which 007 is caught by a drug dealer on an island in the center of an crocodile pool. He uses an extremely bold way to escape - directly stepping on the brain bags of a series of crocodiles in the pool and jumping ashore! (it is said that the stuntman was bitten by the last crocodile. Fortunately, he escaped with extra thick boots.)

The crocodile pool is a square with length and width of 100m, the center coordinate is (0,0), and the northeast corner coordinate is (50,50). The pond core island is a circle with a diameter of 15 meters with (0,0) as the center. Given the coordinates of crocodiles distributed in the pool and the maximum distance 007 can jump at one time, you need to show him the shortest escape path - the so-called "shortest" means that 007 has the least steps to jump.

Input format:

First, the first line gives two positive integers: the number of crocodiles   N (≤ 100) and 007 maximum distance that can jump at one time   D. subsequently   N   Lines, each line gives the name of a crocodile   (x,y)   Coordinates. Note: no two crocodiles will stay at the same point.

Output format:

If 007 is likely to escape, first output the minimum number of steps 007 needs to jump in the first line, and then from the second line, each line gives the coordinates of the crocodile to jump in each step from the pond core island to the shore   (x,y). If it is impossible to escape, output 0 as the number of jump steps on the first line. If the shortest path is not unique, the nearest solution of the first hop is output. The problem ensures that such a solution is unique.

Input example 1:

17 15
10 -21
10 21
-40 10
30 -50
20 40
35 10
0 -10
-25 22
40 -40
-30 30
-10 22
0 11
25 21
25 10
10 10
10 35
-30 10

No blank lines at the end

Output example 1:

4
0 11
10 21
10 35

No blank lines at the end

Input example 2:

4 13
-12 12
12 12
-12 -12
12 -12

No blank lines at the end

Output example 2:

0

No blank lines at the end

——————————————————I'm a dividing line——————————————————

This problem is based on the original problem and requires the output of the shortest path (refers to the number of steps to jump). Using dfs should be the simplest. You only need to make a little change in the function of the original topic: 1. After judging that it can succeed, update the shortest path. 2. Pay attention to separate recursive processing for the first jump during subsequent recursion.

floyd algorithm can also be used to find the minimum number of steps to jump at any point. Then find all possible points to jump out. If K is the jumping point and I is the starting point, then a[i][k] is the shortest circuit. The smallest one can be found later (according to the first step in case of equality).

Although the bfs I use is not easy to write about this problem, it has a clear idea. It can be divided into the following steps:

1. First of all, the extensive search is sequential, as long as it is ensured that the initial team can be joined from small to large according to the origin of the first jump distance. Do a wide search according to this sequence. When you reach a node that can jump out, the number of steps you get must be the optimal solution.

2. The specific node information structure is defined as follows:

struct node{

       int x,y; //coordinate

       int pre,num; //Previous node and current node (structure array can be accessed with this value)

       union{

              int fdis; //Distance of the first step

              int step; //Number of steps to jump

       }data;

}cro[maxn];

Note that I use the common body, because the first time I jump out, I need to record the distance information to the origin for sorting; Just record the steps at the following nodes.

Let's enjoy the code~~

Code:

Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int visited[maxn]; //Determine whether to access
struct node{
	int x,y;
	int pre,num;
	union{
		int fdis;
		int step;
	}data;
}cro[maxn];
int dis_to_O(int x,int y) //Calculate the square of the distance from the node to the origin
{
	return x*x+y*y;
}
int getdis(node n1,node n2) //Calculate the square of the distance between two nodes
{
	return (n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y);
}
bool cmp(node n1,node n2) //sort's comparison function, sorted by distance from small to large
{
	return n1.data.fdis<n2.data.fdis;
}
int main()
{
	//memset(visited,0,sizeof(visited)); // No, the global variable should be 0 automatically
	int n,d;
	cin>>n>>d;
	if(d>=50-7.5){ //Deal with situations that can jump out in the first step
		cout<<1;
		return 0;
	}
	for(int i=0;i<n;i++){
		cin>>cro[i].x>>cro[i].y;
		cro[i].num=i;
		if(dis_to_O(cro[i].x,cro[i].y)<=7.5*7.5||(abs(cro[i].x)>=50||abs(cro[i].y)>=50))
		visited[i]=1; //Remove crocodiles on shore
	}
	vector<node>v; //Store the nodes of the first hop for sorting
	for(int i=0;i<n;i++)
	if(!visited[i]&&(d+7.5)*(d+7.5)>=dis_to_O(cro[i].x,cro[i].y)){ //The step + radius distance is greater than the distance to the origin
		visited[i]=1;
		cro[i].data.fdis=sqrt(dis_to_O(cro[i].x,cro[i].y))-7.5; //Initialize first step distance
		v.push_back(cro[i]);
	}
	sort(v.begin(),v.end(),cmp); //sort
	queue<node>q;
	for(int i=0;i<v.size();i++){ //Join the team in order
		int k=v[i].num; //Find this node
		cro[k].data.step=1; //Change common structure to step
		cro[k].pre=-1; //Set the first go to - 1
		q.push(cro[k]);
	} 
    vector<node>().swap(v); //Free up space
    int ans=0; //Record minimum steps
    node p;
    while(!q.empty()){
    	p=q.front();
    	q.pop();
    	if(abs(p.x)+d>=50||abs(p.y)+d>=50){ //Find something to jump out of
    		ans=p.data.step; The number of steps is the answer-1(The last jump hasn't been counted yet)
    		break;
		}
		for(int i=0;i<n;i++)
		if(!visited[i]&&d*d>=getdis(p,cro[i])){ //Adjacent points join the team
			cro[i].data.step=p.data.step+1;
			cro[i].pre=p.num;
			q.push(cro[i]);
			visited[i]=1;
		}
	}
	if(ans==0) cout<<0; //The ans has not been updated. There must be no solution
	else{
		cout<<ans+1<<endl;
		vector< pair<int,int> >road; //Store path information x to y
		while(p.pre!=-1){//The loop process looks back along the node
			road.push_back(pair<int,int>(p.x,p.y)); 
			p=cro[p.pre];
		}
		road.push_back(pair<int,int>(p.x,p.y)); //Don't forget the first point
		for(int i=road.size()-1;i>=0;i--){ //Reverse output
            cout<<road[i].first<<" "<<road[i].second;
            if(i) cout<<endl;
        }
		vector< pair<int,int> >().swap(road); //Free up space
	}
	return 0;
}

result:

Posted by heropage on Sun, 28 Nov 2021 10:37:26 -0800