從圖中指定的一點出發走到某一目標點如果存在多種不同的走法,
最短的是哪條路?其長度是多少?
圖論中解決上述問題的方法都屬於最短路演算法。由於圖的特點不同、
儲存結構不同、確立演算法的側重方向不同,所以演算法是多種多樣的。
一 無權圖及樹網
在無權圖中,路徑長度只與路徑上的點數有關,而與路徑上的邊權和點權無關。
例如廣搜那節課例題2「方格圖上求從s到e的最短路」一題。
不少多維(多分量)的圖(包括許多抽象圖)的最短路都屬於此類。
由於廣搜就是逐層展開的,所以很適合解決此類問題。
例題1 跳棋
某種跳棋共有5個格仔排成一排,
其中兩格放黑子、兩格放白子,還有一格為空。
跳棋規則允許緊鄰空格的棋子走入空格,還允許把乙個棋子隔著另乙個棋子跳入空格。
求把棋子的一種分布狀態變成另一種分布狀態至少經過多少步?
先輸入乙個長度5且含有兩個1、兩個2、乙個0的數字串,表示原來的分布狀態,
再輸入另乙個長度5且含有兩個1、兩個2、乙個0的數字串,表示後來的分布狀態。
輸出就是最少步數。 分析
把5個位置看成「5維空間(5個分量決定)中的點」,問題就是求從出發點到目標點的最少步數了。
由於圖中的點可能被重複搜尋,所以需要標記搜過的點。(雜湊登記)
又由於每個點的步數都可以從其上游一點的步數加1求得,所以應當建立所有點的步數表。
#include
#include
#include
#include
using namespace std;
int s[3][3][3][3];
string a,b,c;
queueq;
void bfs()
} q.pop(); }
}int main()
由於在樹狀結構中,任意兩點間的路徑是唯一的,因此,廣搜可以求得最短路。
它既是最短路也是最長路。
練習 1 倒公尺
3個儲存公尺的容器容量分別是3、5、8公升,
如果分別放有1、2、5公升公尺,最少倒幾次公尺能評分為兩個4公升?倒幾次能倒成2、5、1公升?
輸入第一行3個整數分別代表3、5、8公升容器中原有公尺數,
第二行3個整數分別代表3、5、8公升容器中希望的公尺數。
如果倒得成就輸出最少倒公尺次數,否則輸出-1.
樣例輸入
0 2 7
3 1 5
輸出 2
樣例說明:
0 2 7倒成 0 1 8 倒成 3 1 5
2 九宮格遊戲
3行3列9個格仔中分別放著1到8的8個數字另有乙個空格。
每次可把緊鄰空格的數字移入空格,至少移動多少次才能變為目標分布?
如果無法實現輸出-1,否則輸出最少移動次數。
輸入3個長度為3的數字串表示原來的分布,
在輸入3個長度為3的數字串表示後來的分布。
0表示空格。
3 noip提高組2002 字串變換
4 noip提高組2007 樹網的核
5 海淀2013 拉燈
拉燈遊戲 lamp.cpp|c|pas
n盞燈從左到右放成一排,每盞燈由乙個拉線開關來控制。
開始燈都未亮,求在滿足下面拉燈規則的前提下,把所有燈都拉亮的最少拉燈線次數。 規則
拉第i盞燈的燈線必須同時滿足下面兩個前提條件:
① 若i>1,則第i-1盞燈必須是滅著的。
② 若i>2,則號數不大於i-2的燈都是亮著的。
輸入檔名為lamp.in中僅有乙個正整數n,代表燈盞總數。
輸出檔案lamp.out中也僅有乙個整數表示最少拉燈線次數。
輸入輸出樣例
lamp.in 3
lamp.out 5
樣例說明:
原來3盞燈的狀態 滅滅滅
拉1燈變成 亮滅滅
拉3燈變成 亮滅亮
拉1燈變成 滅滅亮
拉2燈變成 滅亮亮
拉1燈變成 亮亮亮
資料範圍:
80%的資料滿足n<20
90%的資料滿足n<30
100的資料滿足n<100
選作noip2013day2 華容道
二 可拓撲圖
1 直接計算 例如noip普及組2004 花生採摘
2 動歸 例如跳馬、飛翔、傳遞物品等
最長單調子串行的平方演算法也可看做此類演算法,它自然而然就是乙個拓撲序列,
所以按拓撲順序動歸很容易進行。
由於無圈,所以地推關係得以實現。
例題2 海淀2010競賽 限體力上樓梯
三 上樓梯 程式檔案主名stairs
明明上n級台階可用4種步幅,當然每種步幅花費的體力也不一樣,對應關係如下:
步幅大小 體力花費
1 1
2 3
3 6
4 10
明明開始共有m個體力,求他最少要跨多少步才能上完所有台階?
輸入檔名為stairs.in。其中只有n和m兩個正整數,中間用空格做間隔符。0
對於30%的資料,m<100
對於60%的資料,m<10000
對於80%的資料,m<1000000
對於100%的資料,m<10^19
輸出檔名為stairs.out,其內容只有題目所求的最少步數這乙個數。
輸入輸出樣例
stairs.in的內容為:
3 5則stairs.out的內容為: 2
分析 此圖顯然拓撲,而且屬於最短路型別。
可設f[i][j]為用j個體力上i級台階的最少步數
#include
#include
using namespace std;
ifstream fin("stairs.in");
ofstream fout("data.out");
//f[louti][tili]=最少步數
int f[4010][10000];
int main() ;
for(i=0;i
for(j=i;j
for(k=1;k<=4;k++)
if(f[i][j]+1
f[i+k][j+t[k]]=f[i][j]+1;
for(j=n;j<=m;j++)
s=min(s,f[n][j]);
fout<
return 0; }
練習6 1變n的最小代價
如果整數c=a*b,
則c可變成c+a,代價是b。
c也可變成c+b,代價是a。
求從1變成n的最小總代價。
輸入正整數n,n<200000
輸出最小總代價。
7 noip提高組2009 烏龜棋
8 noip提高組2005 過河
9 跳馬三問
在乙個很大(座標不限、可正可負)的棋盤上,馬從a行b列出發,
只許向右跳(右上或右下不限),
求跳到c行d列最少跳多少部?最多多少部?共有多少種不同跳法?
輸入a、b、c、d4個整數, 0
10 三維飛彈攔截
bomb
題目描述
一場戰爭正在a國與b國之間如火如荼的展開。
b國憑藉其強大的經濟實力開發出了無數的遠端攻擊飛彈,b國的領導人希望,通過這些飛彈直接毀滅a國的指揮部,從而取得戰鬥的勝利!當然,a國人民不會允許這樣的事情發生,所以這個世界上還存在攔截飛彈。
現在,你是一名a國負責飛彈攔截的高階助理。
b國的飛彈有效的形成了三維立體打擊,我們可以將這些飛彈的位置抽象三維中間的點(大小忽略),為了簡單起見,我們只考慮乙個瞬時的狀態,即他們靜止的狀態。
攔截飛彈設計非常精良,可以精準的引爆對方飛彈而不需要自身損失,
但是a國面臨的乙個技術難題是,這些飛彈只懂得直線上公升。
精確的說,這裡的直線上昇指xyz三維座標單調上公升。
給所有的b國飛彈按照1至n標號,一枚攔截飛彈可以打擊的物件可以用乙個xyz嚴格單調上公升的序列來表示,例如:
b國飛彈位置:(0, 0, 0) (1, 1, 0) (1, 1, 1), (2, 2, 2)
乙個合法的打擊序列為:
乙個不合法的打擊序列為
a國領導人將乙份飛彈位置的清單交給你,並且向你提出了兩個最簡單不過的問題(假裝它最簡單吧):
求1枚攔截飛彈最多可以摧毀多少b國的飛彈?
不管是為了個人榮譽還是國家榮譽,更多的是為了飯碗,你,都應該好好的把這個問題解決掉!
輸入檔案
第一行乙個整數n給出b國飛彈的數目。
接下來n行每行三個非負整數xi, yi, zi給出乙個飛彈的位置,你可以假定任意兩個飛彈不會出現在同一位置。
輸出檔案
輸出檔案僅有1行。輸出乙個整數p,表示一枚攔截飛彈之多能夠摧毀的飛彈數。
樣例輸入
4
0 0 0
1 1 0
1 1 1
2 2 2
樣例輸出 3
資料約定
所有的座標都是[0,106]的整數
對於30%的資料滿足n 31
對於50%的資料滿足n 101
對於100%的資料滿足n 1001
最短路問題 1
本蒟蒻記性不太好怕忘 一樣的說辭 咳,寫這篇最短路的文章來紮實自己的基礎 同時讓自己搞的更明白點 在做圖論題的時候,我們往往會通過最短路來進行一些操作,在這篇和下篇文章裡我將會介紹 dijkstra 和 spfa 兩種常見的方法來解決最短路問題。dijkstra 可以說是最經典的最短路演算法之一了,...
最短路 最短路徑問題
題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。input 共有n m 3行,其中 第一行為乙個整數n。第2行...
最短路總結1 最短路問題概述與樸素dijkstra
最短路系列鏈結 最短路總結1 最短路問題概述與樸素dijkstra 最短路總結2 堆優化dijkstra 最短路總結3 bellmanford 最短路總結4 spfa及應用 最短路總結5 floyd 1.最短路問題概述 若網路中的每條邊都有乙個數值 長度 成本 時間等 則找出兩節點 通常是源節點和阱...