1. 程式人生 > >PTA 旅遊規劃(25 分)

PTA 旅遊規劃(25 分)

title 收費 () 輸出 格式 分開 i++ namespace push

7-10 旅遊規劃(25 分)

有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。現在需要你寫一個程序,幫助前來咨詢的遊客找一條出發地和目的地之間的最短路徑。如果有若幹條路徑都是最短的,那麽需要輸出最便宜的一條路徑。

輸入格式:

輸入說明:輸入數據的第1行給出4個正整數N、M、S、D,其中N(2N500)是城市的個數,順便假設城市的編號為0~(N?1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨後的M行中,每行給出一條高速公路的信息,分別是:城市1、城市2、高速公路長度、收費額,中間用空格分開,數字均為整數且不超過500。輸入保證解的存在。

輸出格式:

在一行裏輸出路徑的長度和收費總額,數字間以空格分隔,輸出結尾不能有多余空格。

輸入樣例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

輸出樣例:

3 40


#include<bits/stdc++.h>
using namespace std;
#define maxn 0x7fffffff
int mat[505][505],vis[505],pay[505][505];
/*
mat 是圖的鄰接矩陣表示,vis是標記數組 , pay 是花費的鄰接矩陣表示
*/
int dis[505],cost[505],n,m,path[505];  //最短路 + 路徑輸出
//n 是點的個數 標記為 0 ~ n-1 , 
//dis 最短路記錄數組,cost 最小花費記錄數組,path 路徑記錄數組
void dijkstra(int s) //修改後的最短路算法,+path 記錄 和 花費計算
{
  int i,j;
  memset(vis,0,sizeof(vis));//清空標記數組
  for(i=0;i<n;i++)
  {
      /*
      用mat臨接矩陣的值初始化dis 的值
      用pay臨接矩陣的值初始化cost 的值
      */
      dis[i]=mat[s][i]; 
      cost[i]=pay[s][i];
      if(dis[i]!=maxn) //無窮大代表此路不通 path[i] =-1,否則就在路徑加入這個點
          path[i]=s;
      else path[i]=-1;
  }
  vis[s]=1;//起始點標記
  dis[s]=0;//自己到自己的花費cost = 0
  cost[s]=0;
  for(i=1;i<n;i++)
  {
      int k=s,u=maxn;
      /*
      找出到s距離最短&沒標記的點,作為中轉點更新dis值
      */
      for(j=0;j<n;j++)
      {
          if(!vis[j]&&dis[j]<u)
          {
              u=dis[j];
              k=j;
          }
      }
      vis[k]=1;//標記這個點
      for(j=0;j<n;j++)
      {
          if(!vis[j]&&mat[k][j]!=maxn)
          {
              /*
              用這個點更新dis值,cost 和 dis同步更新,參數值相同
              如果把k作為中轉點成功縮減了dis值,就讓k點加入path路徑裏
              */
              if(dis[j]>dis[k]+mat[k][j])
              {
                  dis[j]=dis[k]+mat[k][j];
                  cost[j]=cost[k]+pay[k][j];
                  path[j]=k;
              }
              /*
              最短路徑dis相同的話,選擇花費最少的,最小cost
              */
              else if(dis[j]==dis[k]+mat[k][j])
              {
                  /*
                  如果這個花費更加優,那麽把這個點加入,更新最優秀的路徑
                  最後path裏面記錄的是最優路徑
                  */
                  if(cost[j]>cost[k]+pay[k][j])
                  {
                      cost[j]=cost[k]+pay[k][j];
                      path[j]=k;
                  }
              }
          }
      }
  }
}
void print(int s,int t)
{
    stack<int>q;
    /*
    從path裏溯源t = path[t],返回上一個和t聯通的路徑,由後往前,把s~t路徑放入隊列裏面,然後輸出
    */
    while(t!=s)
    {
        q.push(t);
        t=path[t];
    }
    q.push(t);
    while(!q.empty())
    {
        cout<<q.top()<<" ";
        q.pop();
    }
}
int main()
{
    int s,t,a,b,d,w,i,j;
    cin>>n>>m>>s>>t;
    for(i=0;i<n;i++)
       for(j=0;j<n;j++)
          mat[i][j]=pay[i][j]=maxn;
    /*
    初始化數組,讓距離鄰接矩陣數組值 = 無窮大,花費鄰接矩陣的值 = 無窮大
    這個計算方式對無向圖和有向圖同樣適用,只需要部分修改
    */
    for(i=0;i<m;i++)
    {
        cin>>a>>b>>d>>w;
        if(mat[a][b]>d)
        {
            mat[a][b]=mat[b][a]=d;
            pay[a][b]=pay[b][a]=w;
        }
        else if(mat[a][b]==d)
        {
            if(pay[a][b]>w)
               pay[a][b]=pay[b][a]=w;
        } // 輸入進行處理,最短路
    }
    dijkstra(s); // 尋找從 s 開始 單源最短路
   // print(s,t);// 輸出路徑, S 到 T 的路徑
    cout<<dis[t]<<" "<<cost[t]<<endl;  // dist 指的是 距離 dis[t] 指的是花費
    return 0;
}

  

PTA 旅遊規劃(25 分)