题目来源:
http://www.patest.cn/contests/mooc-ds/06-%E5%9B%BE4
解:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
/*
* 坐标点
* */
class Point
{
public double x;
public double y;
public Point(double x,double y)
{
this.x=x;
this.y=y;
}
@Override
public String toString() {
return "Point [x=" + x + ", y=" + y + "]";
}
//两点之间的距离
public double distance(Point p)
{
return Math.sqrt(Math.pow(p.y-y,2)+Math.pow(p.x-x, 2));
}
}
/*鳄鱼类
* */
class Crocodile
{
public int index ;//鳄鱼标号
public Point point ;//坐标点
public int father ; //上一个鳄鱼的标号
public int distance ; //所经过的路径长度
public ArrayList<Crocodile> corcodiles; //相邻的鳄鱼
public Crocodile(int index ,double x,double y)
{
this.index= index;
this.point = new Point(x,y);
corcodiles= new ArrayList<Crocodile>();
father =-1;
distance =-1;
}
public void print()
{
System.out.print("Point:"+point+" [Crocodiles:");
for(int i=0;i<corcodiles.size();++i)
{
System.out.print(corcodiles.get(i).point+",");
}
System.out.println("]");
}
//判断一条鳄鱼是否与当前鳄鱼距离小雨d
public boolean isNear(Crocodile c,double d)
{
Point p = c.point;
//两点之间的距离
double distance = p.distance(point);
if(d>=distance)
{
return true;
}
return false;
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
//鳄鱼的数量,跳的最远距离
int n = scanner.nextInt();
double d = scanner.nextDouble();
//存储n条鳄鱼
Crocodile[] crocodiles = new Crocodile[n];
//标记鳄鱼是否被访问过
int[] visit = new int[n];
//在中心圆可以访问的鳄鱼
ArrayList<Integer> initial = new ArrayList<Integer>();
Arrays.fill(visit, 0);
Crocodile initialC= new Crocodile(0,0,0); //原点用一条鳄鱼表示
//n条鳄鱼的坐标
for(int i=0;i<n;++i)
{
int x = scanner.nextInt();
int y = scanner.nextInt();
Crocodile c = new Crocodile(i,x,y);
crocodiles[i]=c;
//鳄鱼之间的距离如果小与等于可以跳的距离,就表示它们之间存在一条连线
for(int j=0;j<i;++j)
{
Crocodile crocodile = crocodiles[j];
if(c.isNear(crocodile, d))
{
c.corcodiles.add(crocodile);
crocodile.corcodiles.add(c);
}
}
//如果鳄鱼与原点之间的距离小于15(直径)+可以跳的距离,表示鳄鱼与原点之间存在一条连线
if(c.isNear(initialC, d+7.5))
{
initial.add(i);
c.father=0;
c.distance=1;
}
}
//如果d>河的宽度 就能直接跳到河岸
if(d>=42.5)
{
System.out.println(1);
return ;
}
Stack<Crocodile> stack = new Stack<Crocodile>(); //存储最短路径
boolean isFirst = true; //是否是stack第一次
//广度搜索所有鳄鱼
for(int i: initial)
{
//将所有的鳄鱼设置为未访问
Arrays.fill(visit, 0);
Stack<Crocodile> tempStack = new Stack<Crocodile>();
Crocodile crocodile = crocodiles[i];
Queue<Crocodile> queue = new LinkedList<Crocodile>();
queue.add(crocodile);
while(!queue.isEmpty())
{
crocodile = queue.poll();
visit[crocodile.index]=1;
//将crocodile可达并且未访问的所有鳄鱼加入队列
for(Crocodile c: crocodile.corcodiles)
{
int index = c.index;
if(visit[index]==0 && c.distance==-1 && c.distance<crocodile.distance+1)
{
queue.add(c);
c.distance=crocodile.distance+1; //距离+1
c.father = crocodile.index; //上一个鳄鱼的下标
}
}
//判断能否从该鳄鱼能够逃出
if(canEscape(crocodile,d))
{
//开始回溯父元素,加入到tempstack中
while(crocodile.father!=0)
{
tempStack.add(crocodile);
crocodile = crocodiles[crocodile.father];
}
tempStack.add(crocodile);
if(isFirst)
{
stack = tempStack;
isFirst=false;
}
else
{
if(stack.size()>tempStack.size() || distanceFromO(stack.peek()) >distanceFromO(tempStack.peek()) )
stack = tempStack;
}
break;
}
}
}
printStack(stack);
}
//打印栈中元素
public static void printStack(Stack<Crocodile> stack)
{
if(stack.size()!=0)
System.out.println(stack.size()+1);
else
System.out.println(0);
while(!stack.isEmpty())
{
Crocodile c = stack.pop();
System.out.println((int)c.point.x+" "+(int)c.point.y);
}
}
//鳄鱼与原点的距离
public static double distanceFromO(Crocodile crocodile)
{
Point point = new Point(0,0);//原点
return crocodile.point.distance(point);
}
public static boolean canEscape(Crocodile crocodile,double d)
{
//判断x距离边缘是否小于d
if( (crocodile.point.x+d)>=50 || (crocodile.point.y+d)>=50 || (crocodile.point.x-d)<=-50 || (crocodile.point.y-d)<=-50 )
{
return true;
}
return false;
}
}
参考:
http://blog.csdn.net/axf1766567189/article/details/43406897