101北一女中 資訊選手培訓營 最短路徑 Shortest Path 2012.08. 13 Nan.

Slides:



Advertisements
Similar presentations
七年级数学校本课程 台山市任远中学 李锦明. 1. 最古老的过河问题 1. 最古老的过河问题 一个农民携带一只狼,一只羊和一 箱卷心菜,要借助一条小船过河。 小船上除了农民只能再带狼、羊、 卷心菜中的一样。而农民不在时, 狼会吃羊,羊会吃菜。农民如何过 河呢?
Advertisements

A A A.
专题复习 --- 走进名著 亲近经典 读完《鲁滨孙漂流记》这本精彩的小说 后,一个高大的形象时时浮现在我的眼 前,他就是勇敢的探险家、航海家鲁滨 孙。他凭着顽强的毅力,永不放弃的精 神,实现了自己航海的梦想。 我仿佛看到轮船甲板上站着这样的一 个人:他放弃了富裕而又舒适的生活, 厌恶那庸庸碌碌的人生,从而开始了一.
§4.3 形状相同的图形 风满楼工作组收集整理 你知道小龙虾吗 ? (手抓小龙虾) 有一只用火柴摆成的头朝上的小龙虾,你 能移动图形中的三根火柴,使它头朝下吗? 小游戏: 移一移 !
第六章 遗传和变异 遗传的基本规律. 遗传性状由什么控制呢? 白人和黑人结合,后代是混血儿;马和驴产生骡? 高 + 矮 = 不高不矮 到底遗传有没有规律呢?
为什么爸爸妈 妈是双眼皮, 我是单眼皮? 为什么为什么? 555…. 1 、举例说出相对性状和基因的关系。 3 、理解近亲结婚的危害。 2 、 能够描述控制相对性状的一对基因的 传递特点。
國中教育會考說明 年 5 月 14 日(六) 105 年 5 月 15 日(日)  08:20- 08:30 考試說明  08:20- 08:30 考試說明  08:30-  09:40 社 會  08:30-  09:40 自 然 09:40- 10:20 休息 09:40-
电子商务专业人才培养方案 五年制高职. 一、招生对象、学制与办学层次  (一)招生对象:初中毕业生  (二)学制:五年  (三)办学层次:专科.
牛熊證簡介.
第一节 人口的数量变化.
德 国 鼓 励 生 育 的 宣 传 画.
知识聚焦 光合作用 呼吸作用 条件 场所 原料 产物 物质变化 能量变化 有光无光都可以 需要光 主要是线粒体 叶绿体 二氧化碳、水
控制方长投下的子公司,需要编制合并报表的演示思路
第四章 透镜及其应用 复习.
温 度 定义: 表示物体冷热程度的物理量。 国际单位:开尔文(K) 单位 常用单位:摄氏度(℃) 原理: 根据液体热胀冷缩的性质制成的。
8 企业信息管理的定量分析 第八讲 企业信息管理的定量分析 8.1 企业信息化水平的测评 8.2 企业信息管理绩效的测评.
前进中的山东省昌乐二中.
歷史建築清水國小宿舍群修復工程 施工說明會
成才之路 · 语文 人教版 • 中国古代诗歌散文欣赏 路漫漫其修远兮 吾将上下而求索.
物理3-5选修模块.
第五章 心理应激与心身疾病 护理学院 王芳.
臺北市國民小學101學年度第2學期 辦理祝妳好孕-課後照顧服務說明
2017/3/16 上 (興) 櫃 公 司 僑外資持股情形申報作業.
必修Ⅰ 地球上的水 第三章.
黄牛课件 中国首家新课标免费资源网(不必注册,免费下载) 请记住我们的网址:
第十章 报关.
物理精讲精练课件 人教版物理 八年级(下).
Network Optimization: Models & Algorithms
项目2-1 店铺的定位.
安全管理概论 中海集运安技部冯幸国.
了解太平天国运动的主要史实,认识农民起义在民主革命时期的作用与局限性。
第五章 一般进出口货物报关程序.
第二章 地球上的大气.
遗传规律类推断题及实验设计题解题策略初探
4.4流体微团运动分析 借助于流体微团的概念来分析流体运动的组成 流体运动不同于刚体的一个显著区别:
遗传的基本规律 (一)基因的分离规律.
第一节 孟德尔的豌豆杂交实验.
电在我们日常生活、现代化社会中的应用: 电 是 什 么?.
台州市2011年科学学业考试试题的命制 台州初级中学 郭海平.
成才之路 · 语文 人教版 • 中国古代诗歌散文欣赏 路漫漫其修远兮 吾将上下而求索.
7.5 擴張樹 (Spanning Tree) 一個無向相連圖 G 的子圖 G’ 如果可用最少的邊來連接G 的
第8章 圖形結構(Graphs) 8-1 圖形的基本觀念 8-2 圖形的表示法 8-3 圖形的走訪 8-4 擴張樹
第八章 图 图的基本概念 图的存储结构 图的遍历与连通性 最小生成树 最短路径 活动网络.
The Greedy Method.
圖論 (Graph Theory) B 電機四 大鳥 B 電機四 酋長 B 電機四 炫大
Bellman 查經 兩個有關婚宴的比喻 馬太福音 22:1~14, 25:1~13.
建國國小英語教學線上課程 字母拼讀篇(一) 製作者:秦翠虹老師、林玉川老師.
如何寫工程計畫書 臺北市童軍會考驗委員會 高級考驗營 版.
摩擦力.
小太陽兒童人文藝術學院兒童畫展 地點:住院大樓9F、11F外走道( )
第16章 資訊科技在採購中的角色.
第9章 基本图算法 本章内容将包含基本的图形表示法,以及先深搜寻,先广搜寻,拓朴排序,Strongly Connected Components。
数据结构概论 第7章 图 董黎刚 浙江工商大学信电学院 2019年4月8日.
最大網路流 Max (Network) Flow
給定分群下加快最短路徑計算之時空成本考量
教科版六年级下册第一单元第4课 怎样放得更大 莲都区天宁小学 陈建秋.
植物激素的调节 一、生长素的发现过程 动物激素是由内分泌细胞合成与分泌。 1、达尔文实验:①证明单侧光照射能使 产生
单片机原理及应用 实践部分 主讲人:刘 强 四川工商学院单片机教学团队 单片机原理及应用 实践部分 主讲人:刘 强
設備組.
算法基础 上机实验 4 学 期: 2016 (秋).
最短通路问题.
進階資料結構(2) Disjoint Sets
Bellman 查經 處理憂慮 馬太福音 6:25~34.
鏈球的力學分析 日本奧運鏈球冠軍(82米91) 室伏廣治因小腿肌肉受傷,退出杜哈亞運。 俄羅斯「鐵娘子」泰亞娜.李森科 九十五年八月八日在
All Sources Shortest Path The Floyd-Warshall Algorithm
Advanced Competitive Programming
第7章 图.
最大網路流 Max (Network) Flow
高雄市104學年度國民中學 童軍教育聯團露營 活動組簡報
10801: Lift Hopping ★★★☆☆ 題組:Problem Set Archive with Online Judge
Presentation transcript:

101北一女中 資訊選手培訓營 最短路徑 Shortest Path 2012.08. 13 Nan

什麼是最短路徑? A 10 C 7 4 5 D 6 3 B 8 F E

Outline Single Source Shortest Path 單源最短路徑 Dijkstra’s Algorithm Bellman-Ford Algorithm All-pairs Shortest Path 全點對最短路徑 Floyd-Warshall Algorithm

Single Source Shortest Path 找起點到所有點的最短距離(和路徑) Single Source Shortest Path

A 10 C 7 4 5 D 6 3 B 8 F E

使用條件:圖上沒有權值為負之邊 Dijkstra’s Algorithm

A B C D E F inf 「正確聯盟」--從起點到他的點的距離已經確定的點 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F inf A B C D E F 7 10 5 inf A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F inf A B C D E F 7 10 5 inf A B C D E F 7 9 5 13 11 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F inf A B C D E F 7 9 5 13 11 A B C D E F 7 10 5 inf A B C D E F 7 9 5 10 11 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F inf A B C D E F 7 10 5 inf A B C D E F 7 9 5 10 11 A B C D E F 7 9 5 13 11 A B C D E F 7 9 5 10 11 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F 7 9 5 13 11 A B C D E F 7 10 5 inf A B C D E F inf A B C D E F 7 9 5 10 11 A B C D E F 7 9 5 10 11 A B C D E F 7 9 5 10 11 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F inf A B C D E F 7 9 5 13 11 A B C D E F 7 10 5 inf A B C D E F 7 9 5 10 11 A B C D E F 7 9 5 10 11 A B C D E F 7 9 5 10 11 A B C D E F 7 9 5 10 11 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F 7 9 5 10 11 A C 7 4 5 D 6 3 B F E

其他一些要注意的 要記得是找所有可能加進正確聯盟的點最近的,不是找「新加進的點距離誰最近」。 要找出整條路徑的方法:另開一個表格,紀錄他是透過誰更新成現在的值的。

#include <string.h> // 為了用memset這個function所以要include這個 #define INF 2147483647 // 用int的最大值做為無限大 int graph[N][N]; // 假設我們有N個點。這裡存的是邊(i,j)的距離(無向邊) // 沒有邊時的距離就是INF int dist[N]; // 記錄目前要把第i個點加入正確聯盟所需要的距離 int last[N]; // 記錄第i個點是透過誰加入了正確聯盟(等於是存在edge(last[i], i)) int choosed[N]; // 記錄是否已經加入了正確聯盟 int fin_cnt; // 記錄已經加入正確聯盟的點的個數 void init(){ // 初始化 // memset會把整塊記憶體空間都填上零,有歸零作用(但不能用來歸成除了0和-1之外的其他值)。 memset(choosed, 0, sizeof(choosed)); // last = -1代表自己就是root,一開始所有點都是自己的root memset(last, -1, sizeof(last)); // 以idx=0的點作為root開始看距離 dist[0] = 0; choosed[0] = 1; int i; for ( i = 1 ; i < N ; i++ ){ dist[i] = graph[0][i]; // 如果有邊dist就會是該條邊,反之則會是INF if ( dist[i] != INF ) last[i] = 0; } fin_cnt = 1; // 一開始只有一個點在正確聯盟裡

void dijkstra(){ int min; // 用來存這一輪找到的距離最小值 int min_idx; // 用來存這一輪找到距離最小的是哪個點 int i; while ( fin_cnt < N ) { // 如果小於N代表還沒找完 min = INF; // 初始化成INF,用來找最小值 min_idx = -1; // 初始化成-1,之後用來判別有沒有找到新的可用的點 for ( i = 1 ; i < N ; i++ ){ // 跑過所有點,找最小值 if ( choosed[i] == 1 ) // 已經在正確聯盟裡就不考慮 continue; if ( dist[i] < min ){ min_idx = i; min = dist[i]; } if ( min_idx == -1 ) break; // 如果沒找到代表此圖找不到下一個可更新的點 choosed[min_idx] = 1; // 標記min_idx這個點進入了正確聯盟 fin_cnt++; // fin_cnt增加一,代表多了一個點已經確定 // 看看還沒有被選的點,有沒有點能夠透過min_idx這個點而更近的 for ( i = 1 ; i < N ; i++ ){ if ( choosed[min_idx] == 1 ) continue; // 被選過的就跳過 if ( ((dist[min_idx] + graph[min_idx][i]) < dist[i] ){ // 有更近就更新 last[i] = min_idx; dist[i] = dist[min_idx] + graph[min_idx][i];

Bellman-Ford Algorithm 可用在有負邊的情況下,亦可用來檢查負環(negative cycle) Bellman-Ford Algorithm

A B C D E F inf A B C D E F 7 10 inf A B C D E F 7 inf A B C D E F 7 10 5 inf 每次都枚舉所有的邊(i, j),兩個方向都看看是否有變短 也就是看 dist[i] + w(i, j) < dist[j] 或 dist[j] + w(i, j) < dist[i] 是否成立 A 10 C 7 4 5 D 6 3 B 8 F E

A B C D E F 7 10 5 inf A B C D E F 7 9 5 inf 11 A B C D E F 7 10 5 inf 11 A B C D E F 7 9 5 10 11 每次都枚舉所有的邊(i, j),兩個方向都看看是否有變短 也就是看 dist[i] + w(i, j) < dist[j] 或 dist[j] + w(i, j) < dist[i] 是否成立 A 10 C 7 4 5 D 6 3 B 8 F E 第i輪代表的意義:最多透過i條邊而走到該點的最近距離

A B C D E F 7 9 5 10 11 沒有人改變就可以結束了(理論上只有n-1輪,除非有負環) A 10 C 7 4 5 D 6 3 B 8 F E 如果需要知道過程經過的點, 那就要另開表格紀錄最後是透過誰更新成現在的值的

#define INF 2147483647 // 用int的最大值做為無限大 int st[M], ed[M], w[M]; // 假設我們有M條邊。edge(st[i], ed[i])的dist為w[i] int dist[N]; // 記錄目前從起點開始到第i個點的最近距離 int last[N]; // 記錄第i個點是透過誰而得到現在的最近距離 void init(){ // 初始化 int i; for ( i = 0 ; i < N ; i++ ){ dist[i] = INF; // 距離一開始都是無限大 last[i] = -1; // 來源初始化 } dist[0] = 0; // 設起點是編號為0的點 void bellman_ford(){ int i, k, flag = 1; // flag用來記錄有沒有人被改過 for ( k = 1 ; k < N && flag ; k++ ){ // 最多做N-1回 且 flag必須非0 flag = 0; // 預設是沒有人被改過 for ( i = 0 ; i < M ; i++ ){ // 跑過所有的邊 // 先看 st[i]->ed[i] if ( dist[st[i]] + w[i] < dist[ed[i]] ){ dist[ed[i]] = dist[st[i]] + w[i]; last[ed[i]] = st[i]; flag = 1; // 再看 ed[i]->st[i] if ( dist[ed[i]] + w[i] < dist[st[i]] ){ dist[st[i]] = dist[ed[i]] + w[i]; last[st[i]] = ed[i];

All pairs Shortest Path 找所有點到所有點的最短距離(和路徑) All pairs Shortest Path

Floyd-Warshall Algorithm 有負邊仍可用 Floyd-Warshall Algorithm

FW是一個動態規劃的演算法 狀態 fk(i, j): 從i走到j,中間只能經過編號為1~k的點 最佳子結構 (1) fk-1(i, j)的最短路徑 (沒有走到點k的情況) (2) fk-1(i, k)和fk-1(k, j)的最短路徑 (加在一起就是經過點k的情況) 遞迴關係 沒有經過任何其他點就是直接有邊的情況

A B C D E F 7 x 5 3 4 6 A C 7 4 5 D 6 3 B F E

枚舉(i, A)+(A, j) 去跟(i, j)比 A B C D E F 7 x 5 3 4 6 A B C D E F 7 x 5 12 7 x 5 3 4 6 A B C D E F 7 x 5 12 3 4 6 枚舉(i, A)+(A, j) 去跟(i, j)比 A C 7 4 5 D 6 3 B F E

枚舉(i, B)+(B, j) 去跟(i, j)比 A B C D E F 7 x 5 10 12 3 4 6 A B C D E F 7 7 x 5 10 12 3 4 6 A B C D E F 7 x 5 10 12 3 4 15 6 A B C D E F 7 x 5 10 12 3 4 6 枚舉(i, B)+(B, j) 去跟(i, j)比 A C 7 4 5 D 6 3 B F E

枚舉(i, C)+(C, j) 去跟(i, j)比 A B C D E F 7 x 5 10 12 3 4 15 6 A C 7 4 5 D 7 x 5 10 12 3 4 15 6 枚舉(i, C)+(C, j) 去跟(i, j)比 A C 7 4 5 D 6 3 B F E

枚舉(i, D)+(D, j) 去跟(i, j)比 A B C D E F 7 9 5 10 11 16 12 3 x 4 15 6 A B 7 9 5 10 11 16 12 3 x 4 15 6 A B C D E F 7 x 5 10 12 3 4 15 6 A B C D E F 7 9 5 10 11 x 12 3 4 15 6 A B C D E F 7 9 5 10 x 12 3 4 15 6 A B C D E F 7 9 5 10 11 16 12 3 18 4 x 15 6 A B C D E F 7 9 5 10 11 16 12 3 18 4 19 x 15 6 A B C D E F 7 9 5 10 11 16 12 3 18 4 19 15 6 21 A B C D E F 7 9 5 10 11 16 12 3 18 4 19 15 6 x 枚舉(i, D)+(D, j) 去跟(i, j)比 A C 7 4 5 D 6 3 B F E

枚舉(i, E)+(E, j) 去跟(i, j)比 A B C D E F 7 9 5 10 11 16 12 3 18 4 19 15 6 7 9 5 10 11 16 12 3 18 4 19 15 6 21 枚舉(i, E)+(E, j) 去跟(i, j)比 A C 7 4 5 D 6 3 B F E

枚舉(i, F)+(F, j) 去跟(i, j)比 A B C D E F 7 9 5 10 11 16 12 3 18 4 19 15 6 7 9 5 10 11 16 12 3 18 4 19 15 6 21 枚舉(i, F)+(F, j) 去跟(i, j)比 A C 7 4 5 D 6 3 B F E

A B C D E F 7 9 5 10 11 16 12 3 18 4 19 15 6 21 Done~! A C 7 4 5 D 6 3 B F E 如果需要知道過程經過的點, 那就要另開表格紀錄最後是透過誰更新成現在的值的

關於開表格的方式 本來狀態fk(i, j)算是有三維,應該要是三維表格的。 但因為每輪的k只需要上一輪的k-1時的資訊就好,而表格每格在更新之前就是k-1時的情況,所以可以只用二維。

#define INF 2147483647 // 用int的最大值做為無限大 int graph[N][N]; // 假設我們有N個點。這裡存的是邊(i,j)的距離(無向邊) // 沒有邊時的距離就是INF int dp[N][N]; // 用來做DP,紀錄距離的表格,初始化會等於graph[i][j] int last[N][N]; // 記錄目前要把第i個點加入正確聯盟所需要的距離 void init(){ // 初始化 int i, j; for ( i = 0 ; i < N ; i++ ){ for ( j = 0 ; j < N ; j++ ){ dp[i][j] = graph[i][j]; // 如果(i, j)有邊就會是該條邊,反之則會是INF last[i][j] = -1; // -1代表沒經過任何點 } void floyd_warshall(){ int i, j, k; for ( k = 0 ; k < N ; k++ ){ for ( i = 0 ; i < N ; i++ ){ for ( j = 0 ; j < N ; j++ ){ // 起點或終點是當前嘗試的點k 或是起點等於終點 就跳過 if ( i == j || i == k || j == k ) continue; if ( dp[i][k] + dp[k][j] < dp[i][j] ){ // 透過點k有更近就更新 dp[i][j] = dp[i][k] + dp[k][j]; last[i][j] = k; }

無向邊時可以直接對稱做 #define INF 2147483647 // 用int的最大值做為無限大 int graph[N][N]; // 假設我們有N個點。這裡存的是邊(i,j)的距離(無向邊) // 沒有邊時的距離就是INF int dp[N][N]; // 用來做DP,紀錄距離的表格,初始化會等於graph[i][j] int last[N][N]; // 記錄目前要把第i個點加入正確聯盟所需要的距離 void init(){ // 初始化 int i, j; for ( i = 0 ; i < N ; i++ ){ for ( j = i ; j < N ; j++ ){ // 如果(i, j)有邊就會是該條邊,反之則會是INF; i == j  0 dp[i][j] = dp[j][i] = graph[i][j]; last[i][j] = last[j][i] = -1; // -1代表沒經過任何點 } void floyd_warshall(){ int i, j, k; for ( k = 0 ; k < N ; k++ ){ for ( i = 0 ; i < N ; i++ ){ for ( j = i + 1 ; j < N ; j++ ){ // 起點或終點是當前嘗試的點k 就跳過 if ( i == k || j == k ) continue; if ( dp[i][k] + dp[k][j] < dp[i][j] ){ // 透過點k有更近就更新 dp[i][j] = dp[j][i] = dp[i][k] + dp[k][j]; last[i][j] = last[j][i] = k; }

看完影片你必須要知道的事 單源最短路徑的問題定義 Dijkstra的操作過程 Dijkstra和Prim的相同與相異之處 Bellman-Ford的可用條件與操作過程 Bellman-Ford之於偵測負環的做法 全點對最短路徑的問題定義 Floyd-Warshall的DP狀態、最小子結構與遞迴式 Floyd-Warshall的bottom-up DP的實作 以上三種演算法的回溯方法(找出路徑的方法)