
Dijkstra算法常见用于地图寻路,但是具体怎样使用,还是有可讨论的内容的。
一、建立地图(二维数组)并在地图上设置可通行与不可通行(白色表示)的点。然后选择一个位置放置英雄(英字),选择一个位置作为目标(空方框)。
二、从地图生成逻辑的图。
1、所有的位置统一编号,采用的方法是:行坐标*宽度+列坐标。
2、每个位置只与周围八个点相连,即彼此之间有一条边。其中与上下左右的四个点之间的边的权(距离)是1,与斜方向的四个点的边的权(距离)是1.4。
3、简单处理起见,暂时用邻接矩阵法保存图
三、搜寻最短路。
用Dijkstra算法,得到从英雄位置到地图所有点的最短路,并得到路线。
四、展现路线。
使用点显示,在屏幕上展示出可视化的路径。
五、改善方向。
很明显,这种从二维地图转化来的图,节点太多,而节点之间的彼此关联很少,使用邻接矩阵法实在是浪费空间太多。如果改用前向星法,会好很多。
【完整代码展示】
#include<iostream>
#include"windows.h"
#include<sstream> // 字符串流
using namespace std;
int field[20][30]={};
int w=30, h=20;
int hx, hy, tx, ty;
// 邻接数组
int e[601][601];
// n个顶点,m条边,s为起点
int n, m, s;
// 无穷大
int inf= 99999;
struct Point{
// 已经确定标记
int mark;
// 当前的最短路距离
int dis;
// 最短路线
string path;
};
// 节点信息
Point p[1000];
void gotoxy(unsigned char x,unsigned char y){
COORD cor;
HANDLE hout;
cor.X = x;
cor.Y = y;
hout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hout, cor);
}
string int2str(int aInt){
stringstream res;
res << aInt;
string ret;
res >> ret;
return ret;
}
int str2int(string aStr){
stringstream res; // cin+cout
res << aStr;
int ret;
res >> ret;
return ret;
}
void show(){
for (int i=0; i<h; i++){
for (int j=0; j<w; j++){
if (field[i][j]==0){
if (i==hy && j==hx) {
cout << "英";
} else if (i==ty && j==tx){
cout << "□";
} else{
cout << " ";
}
} else {
cout << "■";
}
}
cout << endl;
}
}
void addEdge(int a1, int a2, int a3){
if (a1==303 || a2==303) {
// cout << a1 << " " << a2 << " " << a3 << endl;
}
e[a1][a2]= a3;
}
void makeEdge(int i, int j){
if (field[i][j]==1){
return;
}
int id= i*w+j;
// cout << id << endl;
if (i>0 && field[i-1][j]==0){
int id2= (i-1)*w+ j;
//cout << id << " " << id2 << " " << 1 << endl;
addEdge(id, id2, 10);
}
if (j>0 && field[i][j-1]==0){
int id2= (i)*w+ j-1;
addEdge(id, id2, 10);
}
if (i<h-1 && field[i+1][j]==0){
int id2= (i+1)*w+ j;
addEdge(id, id2, 10);
}
if (j<w-1 && field[i][j+1]==0){
int id2= (i)*w+ j+1;
addEdge(id, id2, 10);
}
if (i>0 && j>0 && field[i-1][j-1]==0){
int id2= (i-1)*w+ j-1;
addEdge(id, id2, 14);
}
if (i>0 && j<w-1 && field[i-1][j+1]==0){
int id2= (i-1)*w+ j+1;
addEdge(id, id2, 14);
}
if (i<h-1 && j>0 && field[i+1][j-1]==0){
int id2= (i+1)*w+ j-1;
addEdge(id, id2, 14);
}
if (i<h-1 && j<w-1 && field[i+1][j+1]==0){
int id2= (i+1)*w+ j+1;
addEdge(id, id2, 14);
}
}
void showGraph(){
for (int i=80; i<100; i++){
for (int j=80; j<100; j++){
if (e[i][j]==inf){
cout << -1 << " ";
} else {
cout << e[i][j] << " ";
}
}
cout << endl;
}
}
void findShortest(int s){
// 执行Dijkstra算法
// 首先,起点确定最短路
p[s].mark=1;
p[s].path=int2str(s);
// 第一轮标记
for (int i=0; i<=n-1; i++){
p[i].dis= e[s][i];
p[i].path= int2str(s)+ "-"+ int2str(i);
}
// for (int i=0; i<n; i++){
// cout << p[i].dis << " "<< p[i].path << endl;
// }
// return;
// 循环n-1次,每次增加一个新的最短点
for (int i=1; i<=n-1; i++){
// 找最短的距离,标记为已经确定的最短点
int min= inf, u=0;
for (int j=0; j<n; j++){
if (p[j].mark==0 && p[j].dis<min){
min= p[j].dis;
u=j;
}
}
p[u].mark=1;
// 更新距离(新的最短点加入后,看看有没有变化)
for (int j=0; j<n; j++){
if (p[j].dis> p[u].dis+e[u][j]){
p[j].dis= p[u].dis+e[u][j];
p[j].path= p[u].path+ "-"+ int2str(j);
}
}
}
}
void showPath(string s1){
int a= s1.find('-');
int num=0;
while (a>=0){
string s2= s1.substr(0,a);
s1= s1.substr(a+1);
a= s1.find('-');
int b= str2int(s2);
int x= b%w;
int y= b/w;
// cout << s2 << " " << y << " "<< x<< endl;
gotoxy(x*2, y);
if (num>0){
cout << "·";
}
num++;
}
}
int main(){
// 初始化空场地
for (int i=0; i<h; i++){
for (int j=0; j<w; j++){
if (i==0 || j==0 || i==h-1 || j==w-1){
field[i][j]=1;
}
}
}
// 加障碍1
for (int i=1; i<17; i++){
field[i][8]=1;
}
// 加障碍2
for (int i=1; i<17; i++){
field[h-i][20]=1;
}
hx= 3;
hy= 10;
tx= 26;
ty= 13;
show();
// 图的初始化
n= w*h;
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++){
if (i==j) {
e[i][j]=0;
} else {
e[i][j]=inf;
}
}
}
// 从场地生成图
for (int i=0; i<h; i++){
for (int j=0; j<w; j++){
// 编号思路
int id= i*w+j;
makeEdge(i, j);
//cout << id << endl;
}
}
//showGraph();
findShortest(hy*w+hx);
// for (int i=0; i<n; i++){
// cout << p[i].dis << " "<< p[i].path << endl;
// }
showPath(p[ty*w+tx].path);
// cout << p[ty*w+tx].dis << " "<< p[ty*w+tx].path;
while(1);
return 0;
}
的地图演示&spm=1001.2101.3001.5002&articleId=120952174&d=1&t=3&u=db578b2031a94d50bc4e57b4150497b0)
3429

被折叠的 条评论
为什么被折叠?



