題目背景
在 caima 的 rpg 遊戲中,控制著兩個人 vv 和 jj。 這次 vv 和 jj 掉入了乙個死亡洞穴,洞穴是乙個 n*m 的矩陣。之所以稱之 為死亡洞穴,是因為在這個矩陣中有一些死亡十字。(如下圖中的+)
….+++.
.+.+.
v+.j+
由於 vv 和 jj 被分撒在了兩地,而 jj 還受了重傷,你需要讓 vv 趕到 jj 所 在的地方。為了盡量少的受死亡十字的影響,vv 要盡量遠離這些死亡十字。 我們定義洞穴中兩個格仔(x,y)和(x』,y』)之間的距離為: 也就是說,我們要使得 vv 再去找 jj 的路上,離任意死亡十字的距離都盡 可能的遠。vv 每次可以往乙個格仔的上下左右四個方向走一格。 現在你需要寫個程式,來計算最好情況下離死亡十字最近的距離。
題目描述
輸入輸出格式
輸入格式:
第一行兩個整數 n 和 m,表示矩陣規模。 接下來 n m 列,描述這個洞穴的情況。其中 v 表示 vv 所在的位置; j 表示 jj 所在的位置; . 表示空地;
表示死亡十字。
輸出格式:
一行乙個數字,表示 vv 在去找 jj 的路上,最好情況下離死亡十字最近的距 離。
輸入輸出樣例
輸入樣例
4 4+………
v…j輸出樣例3說明
對於 30% 的資料 n,m≤50。 對於 100% 的資料 n,m≤500。
看完題目感覺無從下手,在教練的一番指點後才發現這居然是一道二分答案+bfs。
思路:二分最近的十字架距離,再bfs判斷是否可以。本題考點主要在於想出二分和如何bfs。
**:
const z:array[1..4,1..2]of -1..1=((1,0),(-1,0),(0,1),(0,-1));
var i,j,k:longint;
m,n,h,t:longint;
ch:char;
fx,fy,lx,ly:longint;
l,r,mid,ans:longint;
a:array[0..501,0..501]of longint;
b,p:array[0..501,0..501]of boolean;
x,y,u:array[0..1000000]of longint;
function bfs(min:longint):boolean;//bfs也就是二分中的check
var i:longint;
begin
p:=b;
h:=1;
t:=1;
x[1]:=fx;
y[1]:=fy;
p[x[1],y[1]]:=false;
if (fx=lx) and (fy=ly) then exit(true);//可以到終點
repeat
for i:=1 to 4 do
if p[x[t]+z[i,1],y[t]+z[i,2]] and (a[x[t]+z[i,1],y[t]+z[i,2]]>=min) then//滿足距離條件
begin
inc(h);
x[h]:=x[t]+z[i,1];
y[h]:=y[t]+z[i,2];
p[x[h],y[h]]:=false;
if (x[h]=lx) and (y[h]=ly) then exit(true);
end;
inc(t);
until t>h;
exit(false);//不可以到終點
end;
begin
read(m,n);
readln;
h:=0;
t:=1;
for i:=1 to m do
begin
for j:=1 to n do
begin
read(ch);
if ch='v' then begin fx:=i; fy:=j; end;
if ch='j' then begin lx:=i; ly:=j; end;
if ch='+' then begin inc(h); x[h]:=i; y[h]:=j; b[i,j]:=false; a[i,j]:=0; u[h]:=0; end
else b[i,j]:=true;
end;
readln;
end;
p:=b;//給每個位置標記上距離,利用bfs必定先找到最優解
repeat
for i:=1 to 4 do
if p[x[t]+z[i,1],y[t]+z[i,2]] then
begin
p[x[t]+z[i,1],y[t]+z[i,2]]:=false;
inc(h);
x[h]:=x[t]+z[i,1];
y[h]:=y[t]+z[i,2];
u[h]:=u[t]+1;
a[x[h],y[h]]:=u[h];
end;
inc(t);
until t>h;
l:=1;
r:=a[fx,fy];
if a[lx,ly]如果大家不明白
給每個位置標記上距離,利用bfs必定先找到最優解
則先做一下這題:
題目描述
給出乙個n*m的01矩陣,求每個點離它最近的數字1的點的距離是多少。距離是曼哈頓距離。(平面上,座標(x1, y1)的點p1與座標(x2, y2)的點p2的曼哈頓距離為:|x1 - x2| + |y1 - y2|.)
輸入格式:
第一行兩個數n,m
後面n行,每行m個字元,為0或1
輸出格式:
共輸出n行,每行m個數,用空格分開。
輸入輸出樣例
輸入樣例
3 40001
0011
0110
輸出樣例
3 2 1 0
2 1 0 0
1 0 0 1
說明50%的資料,n,m<=100
100%的資料,n,m<=1000
這題便是上題目的乙個簡化題,題目更清晰。
**:const z:array[1..4,1..2]of -1..1=((1,0),(-1,0),(0,1),(0,-1));
var i,j,k:longint;
m,n:longint;
a:array[0..1001,0..1001]of longint;
b:array[0..1001,0..1001]of boolean;
ch:char;
h,t:longint;
x,y,u:array[0..1000000]of longint;
begin
h:=0;
t:=1;
readln(m,n);
for i:=1 to m do
for j:=1 to n do
b[i,j]:=true;
for i:=1 to m do
begin
for j:=1 to n do
begin
read(ch);
if ch='1' then//如果為1則入佇列
begin
b[i,j]:=false;
a[i,j]:=0;
inc(h);
u[h]:=0;
x[h]:=i;
y[h]:=j;
end;
end;
readln;
end;
repeat//根據bfs的性質可得第乙個找到的便是那乙個0距離最近的乙個1的距離。
for i:=1 to 4 do
if b[x[t]+z[i,1],y[t]+z[i,2]] then
begin
inc(h);
x[h]:=x[t]+z[i,1];
y[h]:=y[t]+z[i,2];
u[h]:=u[t]+1;
b[x[h],y[h]]:=false;
a[x[h],y[h]]:=u[h];
end;
inc(t);
until t>h;
for i:=1 to m do//輸出便可
begin
for j:=1 to n do write(a[i,j],' ');
writeln;
end;
end.
Sdoi2008 Cave 洞穴勘測
bzoj好了以後去交了這題,算是動態樹補完 題目大意 求一棵樹上任意兩點的連通性 這道題算是真真正正的link cut tree了,之前的動態樹題目都沒有涉及link和cut操作 所以這道題讓我發現了我在寫cut過程中的乙個錯誤,也讓我更加深刻的體會到了link cut tree的優美 對於修改,l...
逃離洞穴 escape
題意 description 小z最近出去旅遊,遇上倒霉事了。他和旅遊團一起去遊洞穴。這裡有n個洞穴,編號為1到n。它們之間,有的有雙向的小路相連,有的卻沒有,不過所有洞穴都通過小路連在了一起,沒有任何兩個洞穴不能相互到達。當遊客們分散在各處的時候,忽然出了些故障,所有燈全部熄滅。這時廣播響起,要求...
1754 逃離洞穴
基礎bfs題目的變形,在結構體裡設定答案,在狀態更新後才進行判斷。兩個基礎的bfs.include include include using namespace std intconst maxn 2000 int vis maxn maxn int rr,cc char map maxn max...