题目1:拯救007
如图所示,007在一个初始位置的岛上,岛的四周为湖泊,假设湖泊内有若干的鳄鱼,鳄鱼静止不动,湖泊的周围是岸边,007采取的拯救方案为:从岛跳至鳄鱼的头上,在跳至另一只鳄鱼的头上,假设007每次跳动的长度为1,写程序,求007能否跳到岸边;
可以把每只鳄鱼看作一个点;
如图所示,把每个鳄鱼的点,看作为一个结点,就可以把这个问题看作为图的dfs或者bfs来进行求解,只有两点之间的距离小于007可跳的范围,即两结点之间存在边;
那么思考选择bfs还是dfs,哪种算法更好呢?
很明显,深度优先更好,因为我们的最终退出条件为跳到岸边即可;
代码如下:
public class LiveOrDie {
private Node[] crocodiles;//鳄鱼的结点
private int xEdge;//x轴上的边界,若设为50,即范围-50~50
private int yEdge;//y轴上的边界,若设为50,即范围-50~50
private Node startPos;//007开始位置
class Node {
int x;
int y;
boolean visited;
public Node(int x, int y) {
this.x = x;
this.y = y;
this.visited = false;
}
//用来判断边是否存在
public boolean canJump(Node node) {
int x1 = this.x - node.x;
int y1 = this.y - node.y;
double distance = Math.sqrt(Math.pow(x1, 2) + Math.pow(y1, 2));
return distance < 1;
}
}
public boolean liveOrDie(Node node) {
if ((Math.abs(node.x) - xEdge) < 1 || (Math.abs(node.y) - yEdge) < 1) return true;
node.visited = true;
for (int i = 0; i < crocodiles.length; i++) {
if (node.canJump(crocodiles[i]) && !crocodiles[i].visited) {
return liveOrDie(crocodiles[i]);
}
}
return false;
}
}
注意:此题目中,并没有实现图的数据结构,因为也没有必须去实现,此题目中涉及的图,其数据结构仅仅多了一层有无边的关系,此题中,我们可以在Node类中,通过visted和canJump方法进行直接判断边是否存在;
若实现的图数据结构,无论是邻接表还是邻接矩阵,这个答案的求得都会更加的麻烦;
题目2:六度空间
一个数学领域的猜想,名为Six Degrees of Separation, 理论指出:你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过6个中间人你就能够认识任何一个陌生人;
即你通过你认识的人的关系层,当这个关系层大于6时,你可以认识任何一个人;
给定社交网络图,请对每个结点计算符合“六度空间”理论结点占总结点的百分比
转换为代码的语言:在给定的一个图的数据结构中,从一个结点出发,相外拓展6次和它有边的结点,是否包含六这个图的所有结点?
考虑算法,向外拓展6层;很明显这道题要运用广度优先,BFS;并且只能做6层,并且需要保存访问到了的结点;
bfs复习:
public void bfs(Vertex v){
Queue que = new Queue();
v.visited = true;
que.add(v);
while(!que.isEmpty){
Vertex v2 = que.pop();
for(v2的邻接点:w){
que.add(w);
w.visited = true;
}
}
}
此题目伪代码:
扫描二维码关注公众号,回复:
9176217 查看本文章
int bfs(Vertex x){
int level = 0;//层数;
int count = 1;//此人肯定认识自己;
Vertx last = x;
Queue queue = new Queue();//得到队列对象
queue.add(x);
x.visited = true;
while(!queue.isEmpty()){
Vertex v = queue.pop();
vertex tail;
for(v的邻接结点 w:v){
if(!w.visited){
w.visited = true;
queue.add(w);
count++;
tail=w;
}
}
//逻辑,每一层的bfs时,当for循环结束时,tail指向了其这一层的最后结点,保存起来;
//v=last时,表示这一层意见循环结束了,level应该+1了;
if(v == last){
level++;
last = tail;//last等于其这一层的最后一个结点
}
if(level == 6) break;
}
return count;
}