飛飛國是乙個傳說中的國度,國家的居民叫做飛飛俠。飛飛國是乙個 n×
m 的矩形方陣,每個格仔代表乙個街區。然而飛飛國是沒有交通工具的。飛飛俠完全靠地面的彈射裝置來移動。每個街區都裝有彈射裝置。使用彈射裝置是需要支付一定費用的。而且每個彈射裝置都有自己的彈射能力。我們設第i行第j列的彈射裝置有 ai
j 的費用和 bi
j 的彈射能力。並規定有相鄰邊的格仔間距離是
1 。那麼,任何飛飛俠都只需要在 (i
,j)支付 ai
j 的費用就可以任意選擇彈到距離不超過 bi
j 的位置了。如下圖(從紅色街區交費以後可以跳到周圍的任意藍色街區.)
現在的問題很簡單。有三個飛飛俠,分別叫做 x,
y,z 。現在它們決定聚在一起玩,於是想往其中一人的位置集合。告訴你
3 個飛飛俠的座標,求往**集合大家需要花的費用總和最低。
輸入的第一行包含兩個整數 n和
m ,分別表示行數和列數。接下來是 2個
n×m 的自然數矩陣,為 ai
j 和 bi
j 最後一行六個數,分別代表 x,
y,z 所在地的行號和列號。
第一行輸出乙個字元 x、
y 或者
z 。表示最優集合地點。第二行輸出乙個整數,表示最小費用。如果無法集合,只輸出一行 no
sample input
4 4
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2
sample output
z 15
100%1≤
n,m≤
150;0≤
aij≤
109;0
≤bij
≤1000
這道題是最短路,看出來了吧,當然我們考場上倒是有人打爆搜的,搜倒是挺快的,但是 wa 了很多點,寫最短路建了邊的話只有 50 分,因為這個邊數是 n2
∗m2 就是**,要優化建邊,倒是在考場上有人不建邊裸跑 dijkstra 擦線過,穩啊。
我們把乙個人從座椅上彈射,想成彈到雲層上,di
s[i]
[j][
k],表示在座標為 (i
,j) 高為
k 的最短距離,你從雲層(i
,j,k
)的地方只能向 (i
,j,k
−1) , (i
−1,j
,k−1
) , (i
,j−1
,k−1
) , (i
+1,j
,k−1
) , (i
,j+1
,k−1
) 的位置移動,只有到地面上才能被彈起,而且只有在被彈起時才會產生花費,在雲層上面走的時候不會產生費用,這種思想你可以想想成水往低處流,就像 minecraft 的水源,實在不行你可以理解為有
k 的能量。這樣就不用建邊,轉移方式固定,然後dijkstra,記得一定要 break,記得一定要清佇列。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define mp make_pair
using
namespace
std;
inline
int read()
while(isdigit(ch))
return i * f;
}const
int maxn = 200 + 5;
int able[4];
int a[maxn][maxn], b[maxn][maxn], n, m, posp[4], mh;
ll dis[maxn][maxn][maxn * 2], ans1, ans2, ans3;
priority_queueint, int> > > q;
struct point ;
point p[4];
inline
int getnum(int x, int y)
inline pair getpos(int num)
inline
void init()
pair k;
#define kf k.first
#define ks k.second
inline
bool judge(int x, int y)
inline
void check(int x, int y, int z, int num)
inline
void dij(int pos)
}else
}if(pos == 1)
else
if(pos == 2)
else
}int main()
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
b[i][j] = read();
for(int i = 1; i <= 3; ++i)
p[i].x = read(), p[i].y = read(), posp[i] = getnum(p[i].x, p[i].y);
dij(1), dij(2), dij(3);
int k = 0; ll ans = 1e17;
if(ans > ans1) ans = (ll)ans1, k = 1;
if(ans > ans2) ans = (ll)ans2, k = 2;
if(ans > ans3) ans = (ll)ans3, k = 3;
if(k == 1) cout
<
<
if(k == 2) cout
<
<
cout
<
<
cout
}
bzoj2143 飛飛俠 最短路
用d i j k 表示走到第 i,j 格,在不彈射的情況下還能再走k步的最小花費,那麼有轉移 d i j k d x y k 1 其中 i,j 和 x,y 相鄰或相等,k 0,表示走到相鄰一格或不走 d i j 0 a i j d x y b i j 表示一次彈射。注意樣例輸入的a,b陣列相反?另外...
bzoj 2143 飛飛俠 最短路
解題思路 這道題點很少,但是邊可能很多,直接建圖做最短路顯然不可行。但是如果把彈射看成獲得了可以走a i j 的能量。這樣就可以直接最短路了。每走一格可看作消耗1的能量,f i j k 表示在i,j這個點且有k的能量的最少費用。每次只要向四個方向走,或者原地不動即可。做三次最短路即可。include...
BZOJ 2143 飛飛俠 最短路
description 飛飛國是乙個傳說中的國度,國家的居民叫做飛飛俠。飛飛國是乙個n m的矩形方陣,每個格仔代表乙個街區。然而飛飛國是沒有交通工具的。飛飛俠完全靠地面的彈射裝置來移動。每個街區都裝有彈射裝置。使用彈射裝置是需要支付一定費用的。而且每個彈射裝置都有自己的彈射能力。我們設第i行第j列的...