图结构最短路径算法

2 篇文章 0 订阅
1 篇文章 0 订阅

找最短路径的图算法

题目:
链接:https://www.nowcoder.com/questionTerminal/571cfbe764824f03b5c0bfd2eb0a8ddf?answerType=1&f=discussion
来源:牛客网
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个位置;1代表小青蛙可以达到的位置。小青蛙初始在(0,0)位置,地下迷宫的出口在(0,m-1)(保证这两个位置都是1,并且保证一定有起点到终点可达的路径),小青蛙在迷宫中水平移动一个单位距离需要消耗1点体力值,向上爬一个单位距离需要消耗3个单位的体力值,向下移动不消耗体力值,当小青蛙的体力值等于0的时候还没有到达出口,小青蛙将无法逃离迷宫。现在需要你帮助小青蛙计算出能否用仅剩的体力值跳出迷宫(即达到(0,m-1)位置)。

输入描述:
输入包括n+1行:
第一行为三个整数n,m(3 <= m,n <= 10),P(1 <= P <= 100)
接下来的n行:
每行m个0或者1,以空格分隔

输出描述:
如果能逃离迷宫,则输出一行体力消耗最小的路径,输出格式见样例所示;如果不能逃离迷宫,则输出"Can not escape!"。 测试数据保证答案唯一

示例1

输入
4 4 10 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1

输出
[0,0],[1,0],[1,1],[2,1],[2,2],[2,3],[1,3],[0,3]

#include<iostream>
#define MAX 101
using namespace std;
int a[11][11]={0};
//定义图的数据结构和方法
class map
{
    private:
        int v[MAX];//顶点表
        int x[MAX];
  	int y[MAX];//(x,y)保存位置
  	int arc[MAX][MAX];//邻接矩阵
  	int numPoint,numEgde;//个数
  	int p[MAX][MAX];
  	int d[MAX][MAX]; 
    public:
  	void creatMap(int n,int m,int a[11][11]);
  	void fd(int n,int m);
  	void show(int m,int pl);
};
map t;
//创建图的数据结构实例
void map::creatMap(int n,int m,int a[11][11])
{
     int k=1;
     //邻接表初始化
     for(int i=1;i<=n*m;i++)
 	for(int j=1;j<=n*m;j++)
  	{
   		arc[i][j]=1000;
   		if(i==j)
    			arc[i][j]=0;
  	}
    //创建邻接矩阵
    for(int i=1;i<=n;i++)
  	for(int j=1;j<=m;j++)
  	{
   		v[k]=k;
   		x[k]=i-1;
   		y[k]=j-1;
           	k++;
	   	if(a[i][j]==1)
	   	{
		    if(i>1 && a[i-1][j]==1)
		     	arc[(i-1)*m+j][(i-2)*m+j]=3;
		    if(j>1 && a[i][j-1]==1)
		     	arc[(i-1)*m+j][(i-1)*m+j-1]=1;
		    if(i<n && a[i+1][j]==1)
		     	arc[(i-1)*m+j][(i)*m+j]=0;
		    if(j<m && a[i][j+1]==1)
		     	arc[(i-1)*m+j][(i-1)*m+j+1]=1;
	   	}	
	}    
}
//求最短路径算法
void map::fd(int n,int m)
{
	 int v,w,k;
	 for(v=1;v<=n*m;++v)
	 {
	  	for(w=1;w<=n*m;++w)
	 	{
	   		d[v][w]=arc[v][w];
	   		p[v][w]=w;
	  	}
	 }
	 for(k=1;k<=n*m;++k)
  		for(v=1;v<=n*m;++v)
   			for(w=1;w<=n*m;++w)
    				if(d[v][w]>d[v][k]+d[k][w])
   				{
     					d[v][w]=d[v][k]+d[k][w];
     					p[v][w]=p[v][k];  
    				}
}
//输出路径
void map::show(int m,int pl)
{
	 int v,k,w; 
	 v=1;
	 w=m;
	 k=p[v][w];
	 if(d[v][w]>pl)
	 {
  		cout<<"Can not escape!"<<endl;
  		return;
 	 }
 	cout<<"["<<x[v]<<","<<y[v]<<"]";
	while(k!=w)
	{
	  	cout<<","<<"["<<x[k]<<","<<y[k]<<"]";
	  	k=p[k][w]; 
	}
	    	cout<<","<<"["<<x[k]<<","<<y[k]<<"]"<<endl;
}
int main()
{
	 int n,m,p;
	 int numP,numE;
	 int a[11][11];    
	 cin>>n>>m>>p;
	 for(int i=1;i<=n;i++)        
  		for(int j=1;j<=m;j++)        
   			cin>>a[i][j];
	 t.creatMap(n,m,a);
	 t.fd(n,m);
	 t.show(m,p);                   
	 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值