给出一个矩阵表示经过没一点时耗费的油量,且在当前的点可以向上下左右四个方向移动,问从起点(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;
}

posted on 2010-12-24 10:20  c++fans  阅读(1030)  评论(0编辑  收藏  举报