description
alice住在森林裡,森林可以看作是n*m的網格,森林裡有怪獸,用『.』表示空地,『+』表示怪獸,『v』表示alice現在的位置,『j』表示alice的家。
alice可以從當前單元格向上下左右相鄰單元格移動,有怪獸的地方也可以走,只不過比較危險,有怪獸的單元格對其他單元格會產生一定的危險係數,假設怪獸位置為(a,b),它對某單元格(r,c)的危險係數為:|r-a|+|c-b|,危險係數越小越危險,每個單元格的危險係數是所有怪獸對它產生的係數的最小值。
alice請你幫她找一條最佳路徑回家,即使得路徑上經過單元格的最小的危險係數最大。
input
輸入第一行包含兩個整數n和m(1<=n,m<=500),表示森林的大小。
接下來n行每行包含m個字元:『.』,『+』,『v』,『j』。
輸入只包含乙個『v』和『j』,而且至少有乙個『+』。
output
輸出最佳路徑中最小的危險係數。
一看,這題比較簡單,實際上,它是乙個運用演算法比較多的問題。
q1:處理每個單元格的危險係數。
這其實就是這個題目的核心問題。
首先,我們可以把每個怪獸的位置用陣列存起來。存入乙個佇列。
對每個怪獸的位置進行寬搜。可以保證先寬搜到的必定是離怪獸最近的。
為什麼?
這個時候,我們就需要嚴謹的證明了。
寬蒐時,我們都是有乙個當前步驟的原點,引申出來的。
舉個例子:當前寬搜到第五步,那麼第五步寬搜到的只有第六步的點。
因此, 可以保證 先寬搜到的必定是離怪獸最近的。
我們現在把這乙個定理姑且叫做「寬搜定理。」
解決了第乙個問題之後,我們又遇到了第二個問題:
q2:怎麼讓那個alice走對路?
我們開始進入到這個題目的第二個核心的問題(也就兩個問題)
首先,我們必須要了解的是:第二個問題不滿足「寬搜定理」。
為什麼?
因為可能你繞路走的危險係數比直走還小呢!
那我們該怎麼辦?
binary search!
我們可以二分答案。然後驗證答案是否可行。
比如說我們現在二分到乙個3的危險度(也就是說這條路上的危險係數不可以小於三,
危險係數越小越危險)
寬蒐時,我們應該多加乙個條件:目標格仔的危險度不可以小於二分值。
於是問題就迎刃而解了。
var
i,j,k,n,s,t,m,s1,s2,h1,h2:longint;
d:array[0..1000000,1..3]of longint;
f:array[0..1000000,1..2]of longint;
c:array[0..1000,0..1000]of char;
data:array[0..1000,0..1000]of longint;
move:array[1..4,1..2]of longint=((1,0),(0,1),(-1,0),(0,-1));
l,r,x:longint;
bj:array[0..1000,0..1000]of boolean;
procedure work;
var i,j,k,x,y:longint;
begin
fillchar(bj,sizeof(bj),0);
fillchar(d,sizeof(d),0);
for i:=1 to f[0,1] do
begin
d[i,1]:=f[i,1];
d[i,2]:=f[i,2];
d[i,3]:=0;
bj[f[i,1],f[i,2]]:=true;
data[f[i,1],f[i,2]]:=0;
end;
i:=0;
j:=f[0,1];
while i0)and(x<=n)and(y>0)and(y<=m) then
begin
inc(j);
d[j,1]:=x;
d[j,2]:=y;
d[j,3]:=d[i,3]+1;
data[x,y]:=d[j,3];
bj[x,y]:=true;
end;
end;
end;
end;
end;
function prepare(t:longint):boolean;
var i,j,k,x,y:longint;
begin
fillchar(bj,sizeof(bj),false);
fillchar(d,sizeof(d),false);
i:=0;
j:=1;
d[1,1]:=s1;
d[1,2]:=s2;
bj[s1,s2]:=true;
while i0)and(x<=n)and(y>0)and(y<=m)and(data[x,y]>=t) then
begin
inc(j);
d[j,1]:=x;
d[j,2]:=y;
bj[x,y]:=true;
end;
end;
end;
end;
exit(false);
end;
begin
fillchar(data,sizeof(data),$7f);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(c[i,j]);
if c[i,j]='+' then
begin
inc(f[0,1]);
f[f[0,1],1]:=i;
f[f[0,1],2]:=j;
end;
if c[i,j]='j' then
begin
h1:=i;
h2:=j;
end;
if c[i,j]='v' then
begin
s1:=i;
s2:=j;
end;
end;
readln;
end;
work;
l:=0;
r:=data[s1,s2];
//writeln(data[s1,s2]);
while l<=r do
begin
x:=(l+r) div 2;
if prepare(x) then l:=x+1
else r:=x-1;
end;
writeln(l-1);
end.
謝謝你的大力支援! NOI題解DAY1 1 回家路線
於我而言,今年的noi簡直殺人。即使我只考了第一天,我就崩潰了。還是我太菜,我自己而言,我最多得五分不能再多了。後來交了 確實只有五分。反正大家知道我菜就對了。有 n 個點和 m 趟列車,第 i 輛列車於 pi 時刻從 xi 號點出發,於 qi 時刻到達 yi 號點。有乙隻小貓要從 1 號點坐車到 ...
P3831 SHOI2012 回家的路 題解
題目傳送門 解法 1 每兩個點都連邊,跑裸的最短路。顯然,n 和 m 非常大,暴力連邊會 tle 和 mle。解法 2 正解 首先,對答案產生貢獻的只有換乘站,所以我們只用連兩種邊 乙個換乘站看作 2 個節點,連邊,邊權為 1 站內換乘 將 x 相等的換乘站相連,y 相等的換乘站相連。其中,起點和終...
題解 P3831 SHOI2012 回家的路
什麼叫分層圖最短路,我不會 kk 感覺自己做法和其他題解不大一樣所以過來發篇題解了。未刻意卡常拿下最優解 就是說給你乙個 n times n 的網格圖和 m 個可換乘點,然後你只能在同一行或同一列 如果在行上移動,就不能在列上移動 反之同理 上移動,除非這個點是可以換乘的。每次走一格花費 2 費,換...