题目
在老电影“007之生死关头”(Live and Let Die)中有一个情节,007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据说当年替身演员被最后一条鳄鱼咬住了脚,幸好穿的是特别加厚的靴子才逃过一劫。)
设鳄鱼池是长宽为100米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径15米的圆。给定池中分布的鳄鱼的坐标、以及007一次能跳跃的最大距离,你需要给他指一条最短的逃生路径 —— 所谓“最短”是指007要跳跃的步数最少。
输入格式:
首先第一行给出两个正整数:鳄鱼数量 N(≤100)和007一次能跳跃的最大距离 D。随后 N 行,每行给出一条鳄鱼的 (x,y) 坐标。注意:不会有两条鳄鱼待在同一个点上。
输出格式:
如果007有可能逃脱,首先在第一行输出007需要跳跃的最少步数,然后从第二行起,每行给出从池心岛到岸边每一步要跳到的鳄鱼的坐标 (x,y)。如果没可能逃脱,就在第一行输出 0 作为跳跃步数。如果最短路径不唯一,则输出第一跳最近的那个解,题目保证这样的解是唯一的。
输入样例 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
输出样例 1:
4
0 11
10 21
10 35
输入样例 2:
4 13
-12 12
12 12
-12 -12
12 -12
输出样例 2:
0
解法
思路
这道题目与常规的图的题目有一个很大的区别,就是它没有直接地告诉你哪些边是存在的,这是需要用距离计算公式来判断的,如果两点之间的距离在可跳范围内,那么它这条边就是实际存在的。
因此解决此题需要进行以下步骤:
- 创建一个图,此图类型为:
typedef struct GNode *PtrToGNode;
typedef PtrToGNode MGraph;
struct GNode
{
int Nv;
WeightType G[MAXN][MAXN];
DataType D[MAXN];
};
其中DataType应该是一个结构体,存储顶点的横纵坐标
- 在创建图的操作中,需要做读图操作,将所给的数据全部读入在图Graph中。其次,还可以把判断边的步骤放在这里,两个for循环嵌套,判断哪些点是相邻的(即可跳的)。
- 用Floyd算法计算所有点之间的最短路径。
- 用一个SearchFirstJump函数来寻找,所有顶点中,从0,0点能跳到的点。把这些点用一个数组存储起来。
- 用一个SearchEndJump函数来寻找,所有顶点中,能跳上岸的点。把这些点用一个数组存储起来。
- 在步骤4和步骤5的两个数组中,各取一个元素FirstPoint和EndPoint,然后在Floyd算法中得到的Dist数组中能是Dist取最小值的FirstPoint和EndPoint。如果Dist相同,则比较FirstPoint离原点的远近。
- 用PrintResult迭代输出顶点坐标
实现
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXN 100+1
#define INFINITY 10000
int JumpDist = 0;
typedef int Vertex;
typedef int WeightType;
typedef struct DataT DataType;
struct DataT
{
int X;
int Y;
};
typedef struct GNode *PtrToGNode;
typedef PtrToGNode MGraph;
struct GNode
{
int Nv;
WeightType G[MAXN][MAXN];
DataType D[MAXN];
};
typedef struct TestNode *TestFE;
struct TestNode
{
int Num;
Vertex Arr[MAXN];
};
MGraph CreateGraph(int VertexNum)
{
MGraph Graph = (MGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Vertex i,j;
for(i=0; i<Graph->Nv; i++)
for(j=0; j<Graph->Nv; j++)
Graph->G[i][j] = INFINITY;
return Graph;
}
int IsEdge(DataType P1, DataType P2)
{
int deltaX = P1.X - P2.X;
int deltaY = P1.Y - P2.Y;
if(deltaX*deltaX + deltaY*deltaY <= JumpDist*JumpDist)
return 1;
else
return 0;
}
MGraph BuildGraph(int VertexNum)
{
MGraph Graph = CreateGraph(VertexNum);
// Graph->Date[0].X = 0;
// Graph->Data[0].Y = 0;
Vertex i,j;
for(i=0; i<Graph->Nv; i++)
scanf("%d %d", &Graph->D[i].X, &Graph->D[i].Y);
for(i=0; i<Graph->Nv; i++)
{
Graph->G[i][i] = 0;
for(j=i+1; j<Graph->Nv; j++)
{
if(IsEdge(Graph->D[i], Graph->D[j]))
{
Graph->G[i][j] = 1;
Graph->G[j][i] = 1;
}
}
}
return Graph;
}
void Floyd(MGraph Graph, int Path[][MAXN], int Dist[][MAXN])
{
Vertex i,j,k;
for(i=0; i<Graph->Nv; i++)
{
for(j=0; j<Graph->Nv; j++)
{
Dist[i][j] = Graph->G[i][j];
Path[i][j] = -1;
}
}
for(k=0; k<Graph->Nv; k++)
for(i=0; i<Graph->Nv; i++)
for(j=0; j<Graph->Nv; j++)
{
if(Dist[i][k] + Dist[k][j] < Dist[i][j])
{
Dist[i][j] = Dist[i][k] + Dist[k][j];
Path[i][j] = k;
}
}
}
TestFE SearchFirstJump(MGraph Graph)
{
TestFE FirstJump = (TestFE)malloc(sizeof(struct TestNode));
FirstJump->Num = 0;
Vertex i;
int deltaX, deltaY;
for(i=0; i<Graph->Nv; i++)
{
deltaX = Graph->D[i].X;
deltaY = Graph->D[i].Y;
if(deltaX*deltaX + deltaY*deltaY < (JumpDist+7.5)*(JumpDist+7.5))
{
FirstJump->Arr[FirstJump->Num++] = i;
}
}
return FirstJump;
}
TestFE SearchEndJump(MGraph Graph)
{
TestFE EndJump = (TestFE)malloc(sizeof(struct TestNode));
EndJump->Num = 0;
Vertex i;
int deltaX, deltaY;
for(i=0; i<Graph->Nv; i++)
{
deltaX = Graph->D[i].X;
deltaY = Graph->D[i].Y;
if( Graph->D[i].X+JumpDist>=50 || Graph->D[i].X-JumpDist<=-50 || Graph->D[i].Y+JumpDist>=50 || Graph->D[i].Y-JumpDist<=-50)
{
EndJump->Arr[EndJump->Num++] = i;
}
}
return EndJump;
}
int IsClose(MGraph Graph, Vertex V1, Vertex V2)
{
if(pow(Graph->D[V1].X, 2) + pow(Graph->D[V1].Y, 2) < pow(Graph->D[V2].X, 2) + pow(Graph->D[V2].Y, 2))
return 1;
else
return 0;
}
void PrintResult(MGraph Graph, int Path[][MAXN], Vertex Start, Vertex End)
{
int k = Path[Start][End];
if(k == -1)
{
printf("%d %d\n", Graph->D[Start].X, Graph->D[Start].Y);
}
else
{
PrintResult(Graph, Path, Start, k);
PrintResult(Graph, Path, k, End);
}
//printf("%d %d\n", Graph->D[End].X, Graph->D[End].Y);
}
int main()
{
int N;
scanf("%d %d", &N, &JumpDist);
//N = N+1;
if(JumpDist >= 50-7.5)
{
printf("1\n");
}
else
{
MGraph Graph = BuildGraph(N);
int Path[MAXN][MAXN];
int Dist[MAXN][MAXN];
Floyd(Graph, Path, Dist);
TestFE FirstJump = SearchFirstJump(Graph);
TestFE EndJump = SearchEndJump(Graph);
WeightType MinJumNum = INFINITY;
Vertex MinStart, MinEnd;
MinStart = 0;
int i,j, FirstPoint, EndPoint;
for(i=0; i<FirstJump->Num; i++)
{
FirstPoint = FirstJump->Arr[i];
for(j=0; j<EndJump->Num; j++)
{
EndPoint = EndJump->Arr[j];
if(Dist[FirstPoint][EndPoint] < MinJumNum)
{
MinJumNum = Dist[FirstPoint][EndPoint];
MinStart = FirstPoint;
MinEnd = EndPoint;
}
else if(Dist[FirstPoint][EndPoint] == MinJumNum && IsClose(Graph, FirstPoint, MinStart))
{
MinStart = FirstPoint;
MinEnd = EndPoint;
}
}
}
if(MinJumNum == INFINITY)
{
printf("0");
}
else
{
printf("%d\n", MinJumNum+2);
PrintResult(Graph, Path, MinStart, MinEnd);
printf("%d %d\n", Graph->D[MinEnd].X, Graph->D[MinEnd].Y);
}
}
return 0;
}