给出一个矩阵表示经过没一点时耗费的油量,且在当前的点可以向上下左右四个方向移动,问从起点(start_r,start_c)到终点(end_r,end_c)所耗费的最小油量。鉴于个人水平,第一想到的就是Dijkstra算法求最短路径。并且没有使用二叉堆维护当前最小权值,效率较低。
#include<iostream>
#include<vector>
#include<stdio.h>
#include<cstring>
using namespace std;
struct Edge
{
int v;
int cost;
Edge(int vv,int cc): v(vv),cost(cc) {}
};
const int N = 10010,maxValue = 99999999;
vector<Edge> adj[N];
int dist[N],point;
int t,m,n,k,num[105][105],matrix[105][105];
void Dijkstra(int s_point) // Dijistra算法求单源最短路径,s_point 为起点
{
bool s[N];
for(int i = 1;i <= point;++i)
{
dist[i] = maxValue;
s[i] = false;
}
dist[s_point] = 0;
for(int i = 0;i < point-1;++i)
{
int min = maxValue; int u = -1;
for(int j = 1;j <= point;++j)
{
if(s[j] == false && dist[j] < min )
{
u = j;
min = dist[j];
}
}
if ( u == -1 ) break;
s[u] = true;
for(int k = 0;k < adj[u].size();++k)
{
int tempv = adj[u][k].v;
int tempcost = adj[u][k].cost;
if( s[tempv] == false && dist[tempv] > dist[u] + tempcost)
{
dist[tempv] = dist[u] + tempcost;
}
}
}
}
int main()
{
cin>>t;
while(t--)
{
int start_r,start_c,end_r,end_c;
cin>>m>>n;
k = 1;
memset(num,0,sizeof(num));
for(int i = 1;i <= m;++i)
for(int j = 1;j <= n;++j)
{
scanf("%d",&matrix[i][j]);
num[i][j] = k++;
}
cin>>start_r>>start_c>>end_r>>end_c;
for(int i = 1;i <= m;++i) // 构图,如果存在一条边从u(r1,c1)到v(r2,c2),则u->v的权值为matrix[r2][c2]
{
for(int j =1;j <= n;++j)
{
if(num[i][j-1]) {
adj[num[i][j]].push_back(Edge(num[i][j-1],matrix[i][j-1]));
}
if(num[i][j+1]) {
adj[num[i][j]].push_back(Edge(num[i][j+1],matrix[i][j+1]));
}
if(num[i-1][j]) {
adj[num[i][j]].push_back(Edge(num[i-1][j],matrix[i-1][j]));
}
if(num[i+1][j]) {
adj[num[i][j]].push_back(Edge(num[i+1][j],matrix[i+1][j]));
}
}
}
point = k-1; //顶点数
Dijkstra(num[start_r][start_c]);
cout<<dist[num[end_r][end_c]] + matrix[start_r][start_c]<<endl;
for(int i = 0;i < k+2;++i)
{
adj[i].clear();
}
}
return 0;
}