給定一張n個點(編號1,2…n),m條邊的有向圖,求從起點s到終點t的第k短路的長度,路徑允許重複經過點或邊。
注意: 每條最短路中至少要包含一條邊。
輸入格式
第一行包含兩個整數n和m。
接下來m行,每行包含三個整數a,b和l,表示點a與點b之間存在有向邊,且邊長為l。
最後一行包含三個整數s,t和k,分別表示起點s,終點t和第k短路。
輸出格式
輸出佔一行,包含乙個整數,表示第k短路的長度,如果第k短路不存在,則輸出「-1」。
資料範圍
1≤s,t≤n≤1000,
0≤m≤105,
1≤k≤1000,
1≤l≤100
輸入樣例:
2 21 2 5
2 1 4
1 2 2
輸出樣例:
14
/*
a* star
在最短路徑問題中,如果所有邊權都是非負的,那麼就可以使用啟發函式來優化bfs過程。
啟發函式:
dist + f(s)
只要f(s) <= g(s) (以及單調性),就可以保證,當某個狀態s,第一次從優先佇列**來時,它的距離就一定是最短距離了。
1.建立反圖,然後在反向圖上求出從終點t到其他所有點的最短距離,作為每個點的估價函式
2.從起點s開始擴充套件,每次取出當前的估計值最下的點,將其所有能擴充套件到的點全部擴充套件。估計值 = 距離起點的真是距離 + 估價函式
3.當第k次遇到t時,就求出了從s到t的第k短路
*/#include
#include
#include
#include
using namespace std;
typedef pair<
int,
int> pii;
typedef pair<
int, pii> piii;
const
int n =
1010
, m =
200010
;int n, m;
int h[n]
, rh[n]
, e[m]
, w[m]
, ne[m]
, idx;
int dist[n]
, f[n]
, st[n]
;//到每個點的最短距離 點的值 重複次數
int s, t, k;
void
add(
int*h,
int a,
int b,
int c)
void
dijkstra()
);while
(heap.
size()
));}
}}memcpy
(f, dist,
sizeof f);}
inta_star()
});//按估價函式排序
memset
(st,0,
sizeof st)
;while
(heap.
size()
)});
}}return-1
;}intmain()
scanf
("%d%d%d"
,&s,
&t,&k);if
(s == t) k ++
;dijkstra()
;printf
("%d\n"
,a_star()
);return0;
}
在乙個3×3的網格中,1~8這8個數字和乙個「x」恰好不重不漏地分布在這3×3的網格中。
例如:1 2 3
x 4 6
7 5 8
在遊戲過程中,可以把「x」與其上、下、左、右四個方向之一的數字交換(如果存在)。
我們的目的是通過交換,使得網格變為如下排列(稱為正確排列):
1 2 3
4 5 6
7 8 x
例如,示例中圖形就可以通過讓「x」先後與右、下、右三個方向的數字交換成功得到正確排列。
交換過程如下:
1 2 3 1 2 3 1 2 3 1 2 3
x 4 6 4 x 6 4 5 6 4 5 6
7 5 8 7 5 8 7 x 8 7 8 x
把「x」與上下左右方向數字交換的行動記錄為「u」、「d」、「l」、「r」。
現在,給你乙個初始網格,請你通過最少的移動次數,得到正確排列。
輸入格式
輸入佔一行,將3×3的初始網格描繪出來。
例如,如果初始網格如下所示:
1 2 3
x 4 6
7 5 8
則輸入為:1 2 3 x 4 6 7 5 8
輸出格式
輸出佔一行,包含乙個字串,表示得到正確排列的完整行動記錄。
如果不存在解決方案,則輸出」unsolvable」。
輸入樣例:
2 3 4 1 5 x 7 6 8
輸出樣例
ullddrurdllurdruldr
/*
八數碼問題無解, 當且僅當 逆序對數量是奇數.
1~8每個數和最終位置的曼哈頓距離之和
string, unordered_map*/
#include
#include
#include
#include
#include
using namespace std;
intf
(string state)
return res;
}string bfs
(string start)
, dy[4]
=;//上右下左
char op[4]
=;string end =
"12345678x"
; unordered_mapint> dist;
//當前距離
unordered_map st;
//當前狀態是不是被搜過
unordered_mapchar
>> prev;
priority_queueint, string>
, vectorint, string>>
, greaterint, string>>
> heap;
heap.
push()
; dist[start]=0
;while
(heap.
size()
) string source = state;
for(
int i =
0; i <
4; i ++);
heap.
push()
;}swap
(state[x *
3+ y]
, state[a *
3+ b]);
}}} string res;
while
(end != start)
reverse
(res.
begin()
, res.
end())
;return res;
}int
main()
int t =0;
for(
int i =
0; i < seq.
size()
; i++
)for
(int j = i +
1; j < seq.
size()
; j ++)if
(seq[i]
> seq[j]
) t ++;if
(t %2)
puts
("unsolvable");
else cout <<
bfs(g)
<< endl;
return0;
}
《演算法競賽高階指南》 防曬
有c頭奶牛進行日光浴,第i頭奶牛需要minspf i 到maxspf i 單位強度之間的陽光。每頭奶牛在日光浴前必須塗防曬霜,防曬霜有l種,塗上第i種之後,身體接收到的陽光強度就會穩定為spf i 第i種防曬霜有cover i 瓶。求最多可以滿足多少頭奶牛進行日光浴。輸入格式 第一行輸入整數c和l。...
《演算法競賽高階指南》蚯蚓
蛐蛐國最近蚯蚓成災了!隔壁跳蚤國的跳蚤也拿蚯蚓們沒辦法,蛐蛐國王只好去請神刀手來幫他們消滅蚯蚓。蛐蛐國裡現在共有 n 只蚯蚓,第 i 只蚯蚓的長度為 ai 所有蚯蚓的長度都是非負整數,即可能存在長度為0的蚯蚓。每一秒,神刀手會在所有的蚯蚓中,準確地找到最長的那乙隻,將其切成兩段。若有多隻最長的,則任...
演算法競賽高階指南筆記
原碼 原碼就是符號位加上真值的絕對值,即用第一位表示符號,其餘位表示值.比如如果是8位二進位制 其中,第一位為1是負數 1 0000 0001 原 1 1000 0001 原 因此,8位二進位制數的取值範圍 127,127 補碼正數的補碼是其本身 負數的補碼是在其原碼的基礎上,符號位不變,其餘各位取...