DFS和广度优先遍历求两点最短路

DFS求两点最短路。


给定2个点,from和to,代表出发点和结束点,求从from到to的一条最优路径。

从from点开始,以优先深度遍历整个图。

使用一个数组s,对于已经遍历过的顶点,标志为1,回溯的时候重置回0.为的是防止重复遍历图的某个环。

当该点对应的s数组为0时,递归下去决策该点。



package 两点最短路径;

import java.util.ArrayList;

public class DFS求两点最短路 {
	static final int N=8;
	static int from=5,to=6;//出发点到结束点
	static int map[][]={
			{0,0,0,0,0,0,0,0,0},
			{0,0,17,13,0,21,0,0,0},
			{0,0,0,0,11,0,13,0,0},
			{0,7,0,0,22,0,0,0,13},
			{0,0,0,0,0,0,1,0,18},
			{0,0,0,0,0,0,0,10,0},
			{0,0,0,0,0,0,0,0,0},
			{0,0,0,1,0,0,0,0,15},
			{0,0,0,3,0,0,21,0,0}
	};
	
	static int s[]=new int[N+1];
	static int pre[]=new int[N+1];//最终解
	static int temppre[]=new int[N+1];//临时解
	static int best=Integer.MAX_VALUE;
	public static void main(String args[])
	{
		ArrayList list = new ArrayList();
		f(from,0);
		System.out.println("最优路径权值为:"+best);
		System.out.println("最优路为:");
		prin(to);
	}
	
	public static void prin(int n)
	{
		if(n==0)return;
		prin(pre[n]);
		System.out.print(" "+n);
			
	}
	
	public static void f(int n,int sum)
	{
		if(n==to)
		{
			if(best>sum)
			{
				best=sum;
				for(int i =1;i<temppre.length;i++)
				{
					pre[i]=temppre[i];
				}
			}
		}
		else
		{
			for(int i=1;i<=N;i++)
			{
				if(map[n][i]!=0&&s[i]!=1)
				{
					if(sum<best)//剪枝条件,当前耗费小于最优耗费才有必要继续递归
					{
						s[i]=1;
						temppre[i]=n;
						f(i,sum+map[n][i]);
						temppre[i]=0;
						s[i]=0;
					}
				}
			}
		}
	}
}

广度优先遍历,用一个队列存放当前顶点合法的邻接点。

每次出队一个顶点,然后把该顶点的邻接点入队。

每个顶点有一个前驱属性,指向该顶点的前驱节点。

package 两点最短路径;

import java.util.ArrayList;
import java.util.Collections;

public class 广度优先求两点最短路 {
	 public static  class Node implements Comparable<Node>{
		int bh;
		int sum;
		Node pre;
		public Node(int bh,int sum,Node pre){
			this.bh=bh;
			this.sum=sum;
			this.pre=pre;
		}
		
		public int compareTo(Node o) {
			if(this.sum>o.sum)
				return -1;
			else if(this.sum<o.sum)
				return 1;
			return 0;
		}
	}
	
	 static int map[][]={
				{0,0,0,0,0,0,0,0,0},
				{0,0,17,13,0,21,0,0,0},
				{0,0,0,0,11,0,13,0,0},
				{0,7,0,0,22,0,0,0,13},
				{0,0,0,0,0,0,1,0,18},
				{0,0,0,0,0,0,0,10,0},
				{0,0,0,0,0,0,0,0,0},
				{0,0,0,1,0,0,0,0,15},
				{0,0,0,3,0,0,21,0,0}
		};
	 static int from=1,to=6;
	 static Node best = new Node(0,Integer.MAX_VALUE,null);//保存最优解
	 static int N=8;//顶点数
	public static void main(String args[])
	{
		ArrayList<Node> list = new ArrayList<Node>();
		list.add(new Node(from,0,null));
		
		while(list.size()>=1)
		{
			Node temp = list.remove(0);
			if(temp.bh==to)//如果到达目标点
			{
				if(best.sum>temp.sum)
					best=temp;
			}
			else
			{
				for(int i=1;i<=N;i++)//没有到达目标点,则把出队顶点的邻接点纳入队列
				{
					if(map[temp.bh][i]!=0&&ifz(temp,i) && temp.sum<best.sum)//最后一个是剪枝条件,如果当前耗费已经超过了当前最优耗费,则没必要再继续下去了
						
							list.add(new Node(i,temp.sum+map[temp.bh][i],temp));
				}
			}
			Collections.sort(list);//对整个队列进行排序,每次出队耗费最小的一个
		}
		System.out.println("最优权值为:"+best.sum);
		System.out.println("最优路径是:");
		prin(best);
	}
	
	public static void  prin(Node temp)
	{
		if(temp==null)
			return ;
		prin(temp.pre);
		System.out.print(" "+temp.bh);
	}
	
	//判断该邻接点是否是前驱顶点
	public static boolean ifz(Node targer,int targertint)
	{
		Node temp = targer;
		while(temp!=null)
		{
			if(temp.bh==targertint)
				return false;
			temp=temp.pre;
		}
		return true;
	}
}

运行结果:

最优权值为:29
最优路径是:
 1 2 4 6




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值