日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小峰峰的pat甲级刷题记录1030

發布時間:2023/12/20 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小峰峰的pat甲级刷题记录1030 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

很經典的最優路線問題

方法一:dfs

思路:

1.vector數組記錄鄰居關系用于深搜遍歷
2.遍歷過程中優化mindis_to[ ] ,fee[ ]
3.遍歷過程中記錄當前路徑path
4.到達終點時優化最終答案

#include<iostream> #include<vector> using namespace std;int N,M,S,D; vector<int>v[500]; vector<int>path; vector<int>final_path; int final_dis=100000000,final_fee; int dis[500][500]; int fee[500][500]; int mindis_to[500];void dfs(int curnode,int curdis,int curfee) {if(curdis>mindis_to[curnode])return;//深搜第一步,不走冤枉路path.emplace_back(curnode);if(curnode==D){if(curdis<final_dis||(curdis==final_dis&&curfee<final_fee)){final_dis=curdis;final_path=path;final_fee=curfee;}}else{if(curdis<mindis_to[curnode])mindis_to[curnode]=curdis;for(int i:v[curnode])dfs(i,curdis+dis[i][curnode],curfee+fee[i][curnode]);}path.pop_back(); }int main() {int i,j,k,f;cin>>N>>M>>S>>D;while(M--){cin>>i>>j>>k>>f;v[i].emplace_back(j);v[j].emplace_back(i);dis[i][j]=dis[j][i]=k;fee[i][j]=fee[j][i]=f;}for(i=0;i<N;i++)mindis_to[i]=100000000;dfs(S,0,0);for(int i:final_path)cout<<i<<' ';cout<<final_dis<<' '<<final_fee; }

優化mindis_to[ ]的作用

1.首先,可以防止走回頭路導致的段錯誤。這一功能也可以dfs多攜帶一個參數記錄上一個經過的結點,下次不走來實現。

... ... void dfs(...int pre) {......for(int i:v[curnode]){if(i!=pre)dfs(...,curnode); //第一次調用時pre=-1 }}
  • 核心功能:剪枝,不走冤枉路
  • 深搜遍歷鄰接表中“優化mindis_to[ ]”和 “使用vis[ ]標記走過點,只走未走過點的”的比較

  • 二者都可以防止走回頭路
  • vis[]標記法保證每個結點都訪問且只訪問一次,但對任意節點只有一條路徑。
    mindis_to[ ]法走且僅走每一條必須“探索”的路,這些“探索”用于優化到每一結點的最短路徑。
  • 遍歷樹時,mindis_to[ ]法沒有意義,因為每個結點都只有一個前驅。vis[ ]法效果等同于pre法
  • 方法二:dijkstra

    dijkstra : 以最小步伐探索黑暗

    #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int MAXV = 510; const int INF = 1000000000;int n,m,st,ed; int G[MAXV][MAXV],cost[MAXV][MAXV]; int mindis_to[MAXV],mincost_to[MAXV]; int pre[MAXV]; bool vis[MAXV]={false};void dijkstra(int s) {fill(mindis_to,mindis_to+MAXV,INF);fill(mincost_to,mincost_to+MAXV,INF);for(int i=0;i<n;i++)pre[i]=i; mindis_to[s]=0;mincost_to[s]=0;for(int i=0;i<n;i++){int u=-1,MIN = INF; // 尋找已探明且還未標記的最近點,記錄它的序號和距離for(int j = 0;j<n;j++){if(vis[j] == false && mindis_to[j] < MIN){u = j;MIN = mindis_to[j];}}if(u==-1)return; // 無點可標,完成任務vis[u] = true; // 標記ufor(int v=0;v<n;v++) // 以u為中轉站,試圖更新mindis_to[v]{if(vis[v] == false && G[u][v] != INF) // v未訪問且u可直接到達v{if(mindis_to[u] + G[u][v] < mindis_to[v] || (mindis_to[u]+G[u][v]==mindis_to[v] && mincost_to[v] > mincost_to[u] + cost[u][v])){mindis_to[v] = mindis_to[u] + G[u][v];mincost_to[v] = mincost_to[u] + cost[u][v];pre[v] = u; // 記錄前驅}}}} }void dfs(int v) // 打印路徑 {if(v == st){cout<<v<<' ';return;}dfs(pre[v]);cout<<v<<' '; }int main() {int i,j,k,f;cin>>n>>m>>st>>ed;fill(G[0],G[0]+MAXV*MAXV,INF); // 初始化Gwhile(m--){cin>>i>>j>>k>>f;G[i][j]=G[j][i]=k;cost[i][j]=cost[j][i]=f;}dijkstra(st);dfs(ed);cout<<mindis_to[ed]<<' '<<mincost_to[ed]; }

    總結

    以上是生活随笔為你收集整理的小峰峰的pat甲级刷题记录1030的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。