NOIP模擬 BZOJ 2143 飛飛俠

2021-08-10 03:19:02 字數 3252 閱讀 5884

飛飛國是乙個傳說中的國度,國家的居民叫做飛飛俠。飛飛國是乙個 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列的...