一开始看到这题感觉挺难的,没什么头绪,然后我上网查了一些不同的做法,还有一个特别好的图解,看了之后感觉思路就清晰很多了。
这个是我看到一个很不错的图解,可以帮助我们更好地理解题目。
这个则是我做这道题的参考,我觉得比较容易理解,是很不错的参考。
题目分析
- 首先要清楚我们要写的子函数,有save007,save007里面包含函数firstjump,jump,isave和DFS。
- 可以分为以下几种情况:
- 007的步长d>=50-7.5=42.5时,可以直接跳出岛
- firstjump:判断能否跳到第一个点a,即d+7.5>=sqrt(x*x+y*y)
- isave:判断007能否从点a直接跳到岸边,即d>=50-|x|或d>=50-|y|
- jump:判断007能否从点a跳到另一个点b,即d>=sqrt((x1-x2)^2+(y1-y2)^2),如果不能,利用递归,返回上一点继续查找。
首先是建立一个结构体,记录鳄鱼的位置
struct point{ //存储鳄鱼的位置 int x; int y; }point[max];
然后我这题用来矩阵的方法,所以还有个初始化矩阵
void resetvisited() {//初始化标记矩阵 for(int i=0; i<max; i++) visited[i] = 0; }
接着是firstjump函数,判断能否跳到第一个点a,这里的yes和no我在一开始也做了定义
#define max 100 #define Yes 1 #define No 0
int firstjump(int i) {//判断能否从岛上跳到一只鳄鱼上 int x = point[i].x; int y = point[i].y; if( (d+7.5)*(d+7.5) >= (x*x+y*y) ) return Yes; else return No; }
接着判断能否从a点直接跳到湖岸,当007步长大于a点到湖岸的距离时,说明可以到达
int isave(int i) {//判断在一条鳄鱼上时能否跳到岸边 int x = point[i].x; int y = point[i].y; if(x<0) x=-x; if(y<0) y=-y; if(d>50-x || d>50-y) return Yes; else return No; }
jump函数,判断能否从一点跳到另一点上
int jump(int i, int j) {//判断007能否从一条鳄鱼跳到另一条鳄鱼上 int x1 = point[i].x; int y1 = point[i].y; int x2 = point[j].x; int y2 = point[j].y; if(d*d >= (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) return Yes; else return No; }
深搜DFS
int DFS(int i) { int answer; visited[i] = true; if(isave(i)) answer = Yes; else { for(int k=0; k<n; k++) { if(!visited[k] && jump(i, k)) //如果改点未被访问且能从i点跳到k点 { answer = DFS(k); if(answer == Yes) break; } } } return answer; }
最后是save007,利用上面几个函数递归
void save007() { int answer; resetvisited(); //初始化矩阵 for(int i=0; i<n; i++) { if(!visited[i] && firstjump(i))//如果该点未被访问且能跳到该点 answer = DFS(i); if(answer == Yes) break; } if(answer == Yes) cout<<"Yes"; else cout<<"No"; }
总结
这道题主要是利用我们这章学习的图的遍历:DFS和BFS。主要是要掌握好如何遍历图,而且我们这学期学的像树,数组,链表等等,遍历都是很重要的一个内容,很多操作都是在遍历上完成的。
上次的目标完成的不错,所以我会继续看回以前做过的题,做出每章的知识总结。