题目: 利用Dijskra和A*算法实现在地图上(2维0,1矩阵,0代表不可达点,1为可达点,每个点用一个方格表示)两个点之间的最短路径搜索,并能通过矩阵方格颜色显示搜索过程和最终路径。
1、输出矩阵方格颜色
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
#define L 10 //矩阵的大小
int p[L][L]; //记录矩阵的数组
int main()
{
int i, j ;
for(i = 0 ; i < L ; i ++)
for(j = 0 ; j < L ; j ++ )
p[i][j] = 1; //初始化所有点均为1
//cout<<p[1][1];
//将不可达点赋值为0
p[2][5]= 0 ;p[3][5]=0;p[4][5]=0;p[5][5]=0;p[6][5]=0;p[7][5]=0;
//显示数组所有元素
for(i = 0 ; i < L ; i ++)
{
for(j = 0 ; j < L ; j ++ )
{
cout<<p[i][j]<<" ";
}
cout<<endl;
}
for(i = 0 ; i < L ; i ++)
{
for(j = 0 ; j < L ; j ++ )
{
cout<<i + j * L<<" ";
}
cout<<endl;
}
/*
char cmd[40] = {0};
for(i = 1; i < 10000; i++)
{
system("cls");
//sprintf(cmd, "color 0%d", 1); //通过后面数字更改格子颜色
//system(cmd);
for(int j = 0 ; j < L ; j++ )
{
for(int k = 0 ; k < L ; k++ )
{
if(p[j][k] == 1){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN); //显示绿色表示可达
printf("■");//□
}
else{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);//显示红色表示不可达
printf("■");}
}
cout<<endl;
}
_sleep(1000);
}
*/
return 0;
}
效果图:
2、Dijkstra算法
由于在该问题下,每两个相邻的距离可以看成是1,而没有不同的权重,将走不通的看成是0,找到能够从初始点走到终点的最短路径即可。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
/*问题描述:
* 输入n和m,代表n个节点,m条边,然后是m行输入,每行有x,y,z,代表x到y的路距离为z。
* 问题:从1出发到各点的最短路径。
* 测试样例:
7 12
1 2 20
1 3 50
1 4 30
2 3 25
2 6 70
3 4 40
3 6 50
3 5 25
4 5 55
5 6 10
5 7 70
6 7 50
*/
using namespace std;
const int maxn = 100;
int map[maxn][maxn];
int dis[maxn];
int path[maxn];
int vis[maxn];//记录更新过的点
int n;
void dijk(int s)
{
//初始化
memset(path,-1,sizeof(path));
/*INF使用0x3f3f3f3f的好处:
* 1:满足无穷大加一个有穷的数依然是无穷大(在DijKstra算法松弛操作中避免了溢出而出现负数)
* 2:满足无穷大加无穷大依然是无穷大(两个0x3f3f3f3f相加并未溢出)
* 3:初始化时,由于每一个字节为0x3f,所以只需要memset(buf,0x3f,sizeof(buf))即可
*/
memset(dis,0x3f,sizeof(dis)); //初始化为无穷大
memset(vis,0,sizeof(vis));
dis[s] = 0; //自身到自身的距离为0
while(1)
{
int k = 0;
for(int j = 1; j <= n; j++)
{
if(!vis[j]&&dis[j]<dis[k])//找未收录顶点中dis值最小的
k=j; //这里第一次找到的是起点
}
if(!k) return; //没有未收录的点,则返回
vis[k] = 1;
//松弛操作
for(int j = 1; j <= n; j++)
{
//第一次循环只有起点的邻接点距离被更新,每次都更新新找到的点的邻接点
if(dis[j]>dis[k]+map[k][j])
{
dis[j]=dis[k]+map[k][j];
path[j]=k;//路径被改变,重新记录前驱,最短路是由最短路+某一条固定路组成,所以前驱是有效的
}
}
}
}
void print(int x)//x为终点
{
if(x == -1) return;
//递归
print(path[x]);
printf("%d->",x);
}
int main()
{
int m,x,y,z,order;
scanf("%d%d",&n,&m);
memset(map,0x3f,sizeof(map));
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&x,&y,&z);
map[x][y] = z;
}
dijk(1);
scanf("%d",&order);//order为终点
print(path[order]);
printf("%d\n",order);
//打印最短距离
printf("%d\n",dis[order]);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
int Map[maxn][maxn];
int dis[maxn];
int path[maxn];
int vis[maxn];//记录更新过的点
int n;
#define L 10 //矩阵的大小
int p[L][L]; //记录矩阵的数组
void dijk(int s)
{
//初始化
memset(path,-1,sizeof(path));
/*INF使用0x3f3f3f3f的好处:
* 1:满足无穷大加一个有穷的数依然是无穷大(在DijKstra算法松弛操作中避免了溢出而出现负数)
* 2:满足无穷大加无穷大依然是无穷大(两个0x3f3f3f3f相加并未溢出)
* 3:初始化时,由于每一个字节为0x3f,所以只需要memset(buf,0x3f,sizeof(buf))即可
*/
memset(dis,0x3f,sizeof(dis)); //初始化为无穷大
memset(vis,0,sizeof(vis));
dis[s] = 0; //自身到自身的距离为0
while(1)
{
int k = 0;
for(int j = 1; j <= n; j++)
{
if(!vis[j]&&dis[j]<dis[k])//找未收录顶点中dis值最小的
k=j; //这里第一次找到的是起点
}
if(!k) return; //没有未收录的点,则返回
vis[k] = 1;
//松弛操作
for(int j = 1; j <= n; j++)
{
//第一次循环只有起点的邻接点距离被更新,每次都更新新找到的点的邻接点
if(dis[j]>dis[k]+Map[k][j])
{
dis[j]=dis[k]+Map[k][j];
path[j]=k;//路径被改变,重新记录前驱,最短路是由最短路+某一条固定路组成,所以前驱是有效的
}
}
}
}
void print(int x)//x为终点
{
if(x == -1) return;
//递归
print(path[x]);
printf("%d->",x);
}
int main()
{
int m,x,y,z,order;
n = L*L;
memset(Map,0x3f,sizeof(Map));
int i, j ;
for(i = 0 ; i < L ; i ++)
for(j = 0 ; j < L ; j ++ )
p[i][j] = 1; //初始化所有点均为1
//cout<<p[1][1];
//将不可达点赋值为0
p[2][5]= 0 ;
p[3][5]=0;
p[4][5]=0;
p[5][5]=0;
p[6][5]=0;
p[7][5]=0;
//由第一行从左往右,从上往下进行编号,编号xy= i + j * L ;
int xy;
for(int k = 0; k < L*L ; k ++)
{
for(j = 0 ; j < L ; j ++ )//行
for( i = 0 ; i < L ; i ++ ) //列
{
if( i-1 >= 0 ) //与左边的点计算路径
{
Map[i+j*L][i - 1 +j*L] =p[i][j]*p[i-1][j];
Map[i - 1 +j*L][i+j*L] =p[i][j]*p[i-1][j];
}
if( i+1 <L ) //与右边的点计算路径
{
Map[i+j*L][i + 1 +j*L] =p[i][j]*p[i+1][j];
Map[i + 1 +j*L][i+j*L] =p[i][j]*p[i+1][j];
}
if( j - 1 >= 0 ) //与上面的点计算路径
{
Map[i+j*L][i +(j-1)*L] =p[i][j]*p[i][(j-1)];
Map[i +(j-1)*L][i+j*L] =p[i][j]*p[i][(j-1)];
}
if( j + 1 < L ) //与下面的点计算路径
{
Map[i+j*L][i +(j+1)*L] =p[i][j]*p[i][(j+1)];
Map[i +(j+1)*L][i+j*L] =p[i][j]*p[i][(j+1)];
}
}
}
dijk(1);
scanf("%d",&order);//order为终点
print(path[order]);
printf("%d\n",order);
//打印最短距离
printf("%d\n",dis[order]);
return 0;
}
3、A*算法代码
··············································································································
后续待更~~~~~