PTA试题中的“Saving James Bond”

本文介绍了在慕课网上学习陈越老师的《数据结构》课程时遇到的有趣题目——拯救007。通过编写代码实现了一个融合easy和hard版本的解决方案,利用深度优先搜索(DFS)判断是否能到达岸边,并找出最优路径。代码中包含了数据结构的运用,如栈和图的构建,同时涉及距离计算和路径打印等算法细节。
摘要由CSDN通过智能技术生成

最近在慕课上学陈越老师的数据结构这门课程,学课的同时还伴随的刷题,觉得拯救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;
	}
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值