最近在慕课上学陈越老师的数据结构这门课程,学课的同时还伴随的刷题,觉得拯救007这个题还蛮有意思的,在此分享一下我写的代码,希望大佬们指点交流,有问题的地方能够提供宝贵意见。为了方便起见,我将“Saving James Bond”的easy版本和hard版本融在了一个代码里面。
#include <iostream>
#include <math.h>
using namespace std;
const int MaxNum = 101;
const int offset = 50;
const double MaxCost = 100000.0;
struct PositionInfo
{
int order;
int x;
int y;
};
const PositionInfo ERROR = { -2,0,0 };
const PositionInfo SUCCESS = { -1, 0, 0 };
struct StackNode
{
PositionInfo Data;
struct StackNode* Next;
};
struct Graph //结构数组来存储图信息
{
int VertexNum;
int JumpRadius;
PositionInfo *Data;
};
Graph* CreatGraph(int VertexNum, int JumpRadius);
void BuildGraph(Graph* MyGraph);
bool Push(StackNode* S, PositionInfo Data);
PositionInfo Pop(StackNode* S);
bool DFS(Graph* MyGraph);
bool IsArrive(int JumpRadius, PositionInfo P);
PositionInfo IsBestPath(Graph* MyGraph, double* cost, int* path);
PositionInfo FindMinCostVertex(Graph* MyGraph, double* cost, int* path, bool* collected);
void printpath(Graph* G, int path[], int V);
int main()
{
Graph* MyGraph;
int VertexNum, JumpRadius;
int MinCost = MaxCost;
int v,MinV;
PositionInfo MinP;
cin >> VertexNum >> JumpRadius;
MyGraph = CreatGraph(VertexNum, JumpRadius);
BuildGraph(MyGraph);
double* cost = new double[MyGraph->VertexNum];
int* path = new int[MyGraph->VertexNum];
MinP = IsBestPath(MyGraph, cost, path);
cout << "是否可以达到岸边: ";
if (DFS(MyGraph)) cout << "Yes" << endl;
else cout << "No" << endl;
if (MinP.order != ERROR.order)
{
if (MinP.order != SUCCESS.order)
{
cout << "到达岸边的步数: "<< (int)cost[MinP.order] + 1 << endl;
cout << "到达岸边的路径: ";
printpath(MyGraph, path, MinP.order);
}
else
{
cout << "到达岸边的路径: ";
cout << "1";
}
}
//else
// cout << "0";
return 0;
}
Graph* CreatGraph(int VertexNum,int JumpRadius)
{
Graph* MyGraph = new Graph;
MyGraph->VertexNum = VertexNum;
MyGraph->JumpRadius = JumpRadius;
MyGraph->Data = new PositionInfo[MyGraph->VertexNum];
return MyGraph;
}
void BuildGraph(Graph* MyGraph)
{
int i;
for (i = 0; i < MyGraph->VertexNum; i++)
{
cin >> MyGraph->Data[i].x >> MyGraph->Data[i].y;
MyGraph->Data[i].order = i;
}
}
double distance(PositionInfo P)
{
double x = (double)P.x;
double y = (double)P.y;
return (sqrt((x*x + y * y))-7.5);
}
double distance(PositionInfo P1, PositionInfo P2)
{
double x1 = (double)P1.x;
double y1 = (double)P1.y;
double x2 = (double)P2.x;
double y2 = (double)P2.y;
return sqrt(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
bool DFS(Graph* MyGraph)
{
int i;
int n = 0; //记录收录的节点数量
StackNode* S = new StackNode;
S->Next = NULL;
bool* Visit = new bool[MyGraph->VertexNum];
for (i = 0; i < MyGraph->VertexNum; i++) //初始化Visit数组
Visit[i] = false;
if (MyGraph->JumpRadius < 42.5) //一步跳不过去
{
while (n != MyGraph->VertexNum)
{
if (NULL == S->Next)
{
for (i = 0; i < MyGraph->VertexNum; i++) //压入从center出发的第一个元素
if (Visit[i] == false && distance(MyGraph->Data[i]) <= MyGraph->JumpRadius)
{
if (IsArrive(MyGraph->JumpRadius,MyGraph->Data[i])) return true;
Push(S, MyGraph->Data[i]);
Visit[i] = true;
n++;
break;
}
if (i == MyGraph->VertexNum) return false; //踩不上任何点
}
else
{
for (i = 0; i < MyGraph->VertexNum; i++)
{ //查找要达到的下一顶点
if (Visit[i] == false && distance(MyGraph->Data[i], S->Next->Data) <= MyGraph->JumpRadius) //找到
{
if (IsArrive(MyGraph->JumpRadius,MyGraph->Data[i])) return true;
Push(S, MyGraph->Data[i]);
Visit[i] = true;
n++;
break;
}
}
if (i == MyGraph->VertexNum) Pop(S); //没找到
}
}
}
else
return true;
return false;
}
bool Push(StackNode* S, PositionInfo Data)
{
StackNode* NewS = new StackNode;
NewS->Data.x = Data.x;
NewS->Data.y = Data.y;
NewS->Data.order = Data.order;
NewS->Next = NULL;
NewS->Next = S->Next;
S->Next = NewS;
return true;
}
PositionInfo Pop(StackNode* S)
{
StackNode* TempNode;
PositionInfo TempData;
if (NULL == S->Next) return ERROR;
TempNode = S->Next;
S->Next = TempNode->Next;
TempData = TempNode->Data;
delete TempNode;
return TempData;
}
bool IsArrive(int JumpRadius, PositionInfo P)
{
if (abs(P.x) >= (50- JumpRadius) || abs(P.y) >= (50 - JumpRadius)) return true;
else return false;
}
PositionInfo IsBestPath(Graph* MyGraph, double* cost, int* path)
{
int i;
PositionInfo MinPos;
int v;
bool* collected = new bool[MyGraph->VertexNum];
for (i = 0; i < MyGraph->VertexNum; i++) //初始化数组
{
cost[i] = MaxCost;
path[i] = -2;
collected[i] = false;
}
if (MyGraph->JumpRadius < 42.5) //一步跳不过去
{
for (i = 0; i < MyGraph->VertexNum; i++)
{
if (distance(MyGraph->Data[i]) <= MyGraph->JumpRadius)
{
cost[i] = 1.0+ distance(MyGraph->Data[i])/100.0; //开始的每条路径代价不同,越短的代价越小
path[i] = -1; //表示从岛出发 父节点是岛
}
}
while (1)
{
MinPos = FindMinCostVertex(MyGraph, cost, path, collected);
if (MinPos.order == -2) return ERROR;
collected[MinPos.order] = true;
if (IsArrive(MyGraph->JumpRadius, MinPos)) return MinPos; //该顶点可以直接跳到岸边
for (v = 0; v < MyGraph->VertexNum; v++)
{
if (collected[v] == false)
{
if ((distance(MinPos, MyGraph->Data[v]) <= MyGraph->JumpRadius)&&(cost[v] > cost[MinPos.order] + 1.0)) //可以跳到的顶点
{
cost[v] = cost[MinPos.order] + 1.0;
path[v] = MinPos.order;
}
}
}
}
}
else return SUCCESS;
return ERROR;
}
PositionInfo FindMinCostVertex(Graph* MyGraph, double* cost, int* path, bool* collected)
{
double MinCost = MaxCost;
int MinV, V;
for (V = 0; V < MyGraph->VertexNum; V++)
{
if (collected[V] == false)
{
if (cost[V] < MinCost)
{
MinCost = cost[V];
MinV = V;
}
}
}
if (MinCost == MaxCost) return ERROR;
else if (MinCost < MaxCost)return MyGraph->Data[MinV];
}
void printpath(Graph* G, int path[], int V)
{
if (V != -1)
{
printpath(G, path, path[V]);
cout << endl << G->Data[V].x << " " << G->Data[V].y;
}
}