中国大学MOOC-数据结构基础习题集、06-1、Saving James Bond - Hard Version
2015-01-09 23:00
525 查看
题目链接:http://www.patest.cn/contests/mooc-ds/06-1
题目分析:这是一道考察图的广度优先遍历,同时也要借助于Dijstra算法的一道题。题目的背景与上周的05-2是相同的:007被困在一个孤岛上,孤岛的直径是15,池塘的范围是[±50, ±50]。池塘中鳄鱼的条数及坐标,007的跳跃半径通过输入给出。问007能否借助于池塘中的鳄鱼逃出生天?和上周要求不同的是,需要把最短路径长度及最短路径输出,在有多条最短路径的情况下,输出第一跳最近的那条。
特别说明:
1. 是否建立图随意,用若干个数组表示也可以。博主最开始是没有建的,但是这次贴的代码是建好图的(邻接表)。一方面是为了练习自己的编码能力,一方面也是给对建图不熟悉的同学们举个“栗子”。感兴趣的同学可以关注下103~158行。
2. 题目中要求“多条最短路径输出第一跳最近的那条”,博主查找了许多别的资料,最后使用的优先级队列。使用时需要重载小于运算符(即operator<)。将在孤岛上能踩到的所有鳄鱼结点,以距孤岛中心的距离为优先级,放入优先级队列中。然后依次取出,做广度优先遍历。这部分在165~180+行。
3. 在做广度优先遍历时,如果已经可以逃脱,要确定当前是否为最短路径,是则记录路径。可以关注一下198~215行。
4. 求两点间距离的函数,要判断其中一点是不是“岛屿”,如果是的话,结果要加上孤岛的半径。函数的定义在63~78行。
5. 如果Case4过不去的朋友,请试一下我的用例1。如果是Case5过不去的朋友,请试一我的用例2。
建议测试如下数据:
4 20 -27 0 -41 0 0 26 0 40
博主这里输出结果是:3 0 26 0 40
1 42.5
博主这里输出结果是:1
代码分析:
注释写的非常详细,大家可以阅读一下:
AC成果:
题目分析:这是一道考察图的广度优先遍历,同时也要借助于Dijstra算法的一道题。题目的背景与上周的05-2是相同的:007被困在一个孤岛上,孤岛的直径是15,池塘的范围是[±50, ±50]。池塘中鳄鱼的条数及坐标,007的跳跃半径通过输入给出。问007能否借助于池塘中的鳄鱼逃出生天?和上周要求不同的是,需要把最短路径长度及最短路径输出,在有多条最短路径的情况下,输出第一跳最近的那条。
特别说明:
1. 是否建立图随意,用若干个数组表示也可以。博主最开始是没有建的,但是这次贴的代码是建好图的(邻接表)。一方面是为了练习自己的编码能力,一方面也是给对建图不熟悉的同学们举个“栗子”。感兴趣的同学可以关注下103~158行。
2. 题目中要求“多条最短路径输出第一跳最近的那条”,博主查找了许多别的资料,最后使用的优先级队列。使用时需要重载小于运算符(即operator<)。将在孤岛上能踩到的所有鳄鱼结点,以距孤岛中心的距离为优先级,放入优先级队列中。然后依次取出,做广度优先遍历。这部分在165~180+行。
3. 在做广度优先遍历时,如果已经可以逃脱,要确定当前是否为最短路径,是则记录路径。可以关注一下198~215行。
4. 求两点间距离的函数,要判断其中一点是不是“岛屿”,如果是的话,结果要加上孤岛的半径。函数的定义在63~78行。
5. 如果Case4过不去的朋友,请试一下我的用例1。如果是Case5过不去的朋友,请试一我的用例2。
建议测试如下数据:
4 20 -27 0 -41 0 0 26 0 40
博主这里输出结果是:3 0 26 0 40
1 42.5
博主这里输出结果是:1
代码分析:
注释写的非常详细,大家可以阅读一下:
#include <iostream> #include <algorithm> #include <vector> #include <cmath> #include <queue> #include <stack> using namespace std; /* * 所用结构体的声明 * pos 坐标结构体 * vexNode 邻接表中的结点 */ struct pos; template <class T> struct vexNode; /* * 宏定义的声明 * FIRSTSTEP 小岛的半径,固定为7.5 * BORDER 边界的大小,固定为50 * MAXNUM 无穷大 */ #define FIRSTSTEP 7.5 #define BORDER 50 #define MAXNUM 100000000 /* * 全局变量的声明 * vec 存储鳄鱼的坐标 * eVec 邻接表存储图 * pathVec 用来存储路径 */ vector<pos> vec; vector<vexNode<int> > eVec; vector<int> pathVec; struct pos { double x; double y; pos(double a, double b):x(a),y(b) {} }; template <class T> struct vexNode { T data; vexNode<T> *next; vexNode(T d, vexNode<T> *n = NULL):data(d), next(n) {} bool friend operator<(const vexNode &a, const vexNode &b) { int V = a.data; int W = b.data; int dV = vec[V].x * vec[V].x + vec[V].y * vec[V].y; int dW = vec[W].x * vec[W].x + vec[W].y * vec[W].y; return dV < dW; // 出队先出大的,再出小的 } }; /* * 计算两点之间的距离 */ double Distance(pos p1, pos p2, int dis) { double xx = (p1.x - p2.x) * (p1.x - p2.x); double yy = (p1.y - p2.y) * (p1.y - p2.y); if((p1.x == 0 && p1.y == 0) || (p2.x == 0 && p2.y == 0)) { return dis + FIRSTSTEP - sqrt(xx + yy); } else { return dis - sqrt(xx + yy); } } /* * 获得路径 */ vector<int> getPath(int t, int p[]) { vector<int> path; for(; t!=-1; t=p[t]) path.push_back(t); reverse(path.begin(),path.end()); return path; } int main() { int nNum; double dis; cin >> nNum >> dis; // 考虑特殊情况,能否一步迈出 if(dis + FIRSTSTEP >= BORDER) { cout << "1" << endl; return 0; } // 起始点(小岛)也算一个点 vec.push_back(pos(0, 0)); eVec.push_back(vexNode<int>(0)); nNum ++; // 用邻接表存储图 for(int i=1; i<nNum; i++) { double a, b; cin >> a >> b; vec.push_back(pos(a,b)); eVec.push_back(vexNode<int>(i)); } // 开始建图 for(int i=0; i<nNum; i++) { for(int j=0; j<nNum; j++) { if(i != j) { if(Distance(vec[i], vec[j], dis) >= 0) { // 查一查有没有重复的 bool myIFlag = false; vexNode<int> *p = &eVec[i]; while(p -> next != NULL) { p = p -> next; if(p -> data == j) { myIFlag = true; break; } } // 如果没有重复的,就插在最后边 if(myIFlag == false) p -> next = new vexNode<int>(j); // 因为是无向图,也就是双向图,所以另一侧也要插 bool myJFlag = false; vexNode<int> *q = &eVec[j]; while(q -> next != NULL) { q = q -> next; if(q -> data == i) { myJFlag = true; break; } } // 如果没有重复的,就插在最后边 if(myJFlag == false) q -> next = new vexNode<int>(i); } } } } // 相关数据结构的申请 int *dist = new int[nNum]; int *path = new int[nNum]; priority_queue<vexNode<int> > myQueue; // 算法开始 // 1. 在相同的最短路里找第一步最小的放入优先级队列中 vexNode<int> *p = &eVec[0]; while(p -> next != NULL) { p = p -> next; myQueue.push(eVec[p->data]); path[p->data] = 0; } int flag = 1; // flag用来标记是否是第一次 int minDist; // minDist记录最小的dist值 // 2. 从岛屿开始,能到达的所有结点做循环 while(!myQueue.empty()) { // 2.1 初始化 for(int i=0; i<nNum; i++) { dist[i] = -1; path[i] = -1; } // 2.2 从队列中弹出一个结点,从这个结点开始,借助另一个队列,进行BFS vexNode<int> vN = myQueue.top(); myQueue.pop(); path[vN.data] = 0; // 从myQueue队列中取出的结点,parent一定为岛屿(0,0) queue<int> bfsQueue; // 进行BFS所需要的队列 bfsQueue.push(vN.data); dist[vN.data] = 0; // 初始的dist值为0 while(!bfsQueue.empty()) { int W = bfsQueue.front(); bfsQueue.pop(); // 2.3 判定是不是已经可以上岸了 if(fabs(vec[W].x-BORDER)<=dis || fabs(vec[W].x+BORDER)<=dis ||fabs(vec[W].y-BORDER)<=dis ||(vec[W].y+BORDER)<=dis) { // 2.3.1 如果是第一次,更新minDist值,并记录路径 if(flag&&W!=0) { minDist = dist[W]; flag = 0; pathVec = getPath(W, path); } // 2.3.2 如果不是第一次,则比较minDist值与dist值,并更新路径 else if(W!=0 && dist[W] <= minDist) { minDist = dist[W]; pathVec = getPath(W, path); } } // 2.4 如果没有上岸,则将其邻接结点放入队列中,并更新dist与path的值 else { for(int i=1; i<=nNum; i++) { if(Distance(vec[W], vec[i], dis) >= 0 && dist[i] == -1) { bfsQueue.push(i); dist[i]=dist[W]+1; path[i]=W; } } } } } // 3. 输出最终结果 if(pathVec.size() == 0) cout << "0" << endl; else { // 3.1 因为我们把(0,0)也当成结点了,这里不用+1 cout << pathVec.size() << endl; for(int i=0; i<pathVec.size(); i++) // 3.2 因为我们把(0,0)也当成结点了,但是不能让它输出,所以特殊考虑 if(vec[pathVec[i]].x == 0 and vec[pathVec[i]].y == 0) ; else cout << vec[pathVec[i]].x << " " << vec[pathVec[i]].y << endl; } return 0; }
AC成果:
相关文章推荐
- 中国大学MOOC-数据结构基础习题集、05-2、Saving James Bond - Easy Version
- 中国大学MOOC-数据结构基础习题集、06-5、关键活动
- MOOC浙大数据结构 — 06-图2 Saving James Bond - Easy Version (25分)
- 中国大学MOOC-数据结构基础习题集、06-4、How Long Does It Take
- 中国大学MOOC-数据结构基础习题集、06-3、公路村村通
- 中国大学MOOC-数据结构基础习题集、09-3、Hashing - Hard Version
- 中国大学MOOC-数据结构基础习题集、06-2、旅游规划
- 中国大学MOOC-数据结构基础习题集、08-3、Sort with Swap(0,*)
- 中国大学MOOC-数据结构基础习题集、02-3、求前缀表达式的值
- 中国大学MOOC-数据结构基础习题集、04-2、File Transfer
- 中国大学MOOC-数据结构基础习题集、02-2、一元多项式求导
- 中国大学MOOC-数据结构基础习题集、09-2、QQ帐户的申请与登陆
- 中国大学MOOC-数据结构基础习题集、03-2、List Leaves
- PAT-中国大学MOOC-陈越、何钦铭-数据结构基础习题集 00-自测5. Shuffling Machine (20) (简单模拟)【二星级】
- 中国大学MOOC-数据结构基础习题集、04-3、Huffman Codes
- 中国大学MOOC-陈越、何钦铭-数据结构基础习题集 00-自测3-数组元素循环右移问题 (20)
- 中国大学MOOC-数据结构基础习题集、08-1、Talent and Virtue
- 中国大学MOOC-数据结构基础习题集、04-1、Root of AVL Tree
- 中国大学MOOC-数据结构基础习题集、03-3、Tree Traversals Again
- 中国大学MOOC-数据结构基础习题集、05-3、六度空间