1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 498 Solved: 223
[Submit][Status]
Description
The farm has many hills upon which Farmer John would like to place guards to ensure the safety of his valuable milk-cows. He wonders how many guards he will need if he wishes to put one on top of each hill. He has a map supplied as a matrix of integers; the matrix has N (1 < N <= 700) rows and M (1 < M <= 700) columns. Each member of the matrix is an altitude H_ij (0 <= H_ij <= 10,000). Help him determine the number of hilltops on the map. A hilltop is one or more adjacent matrix elements of the same value surrounded exclusively by either the edge of the map or elements with a lower (smaller) altitude. Two different elements are adjacent if the magnitude of difference in their X coordinates is no greater than 1 and the magnitude of differences in their Y coordinates is also no greater than 1.
农夫JOHN的农夫上有很多小山丘,他想要在那里布置一些保镖(……)去保卫他的那些相当值钱的奶牛们。 他想知道如果在一座小山丘上布置一名保镖的话,他总共需要招聘多少名保镖。他现在手头有一个用数字矩阵来表示地形的地图。这个矩阵有N行(1 < N < = 100)和M列( 1 < M < = 70) 。矩阵中的每个元素都有一个值H_ij(0 < = H_ij < =10,000)来表示该地区的海拔高度。请你帮助他统计出地图上到底有多少个小山丘。 小山丘的定义是:若地图中一个元素所邻接的所有元素都比这个元素高度要小(或它邻接的是地图的边界),则该元素和其周围所有按照这样顺序排列的元素的集合称为一个小山丘。这里邻接的意义是:若一个元素与另一个横坐标纵坐标和它的横纵坐标相差不超过1,则称这两个元素邻接。 问题名称:guard 输入格式: 第一行:两个由空格隔开的整数N和M 第二行到第N+1行:第I+1行描述了地图上的第I行,有M个由空格隔开的整数:H_ij. 输入样例:(guard.in): 8 7 4 3 2 2 1 0 1 3 3 3 2 1 0 1 2 2 2 2 1 0 0 2 1 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 1 1 1 0 0 1 2 2 1 1 0 0 1 1 1 2 1 0 输出格式: 第一行:小山丘的个数 输出样例:(guard.out): 3 输出样例解释: 地图上有三个小山丘:每个小山丘的山峰位置分别在左上角(高度为4),右上角(高度为1)和底部(高度为2)。
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes row i of the matrix with M space-separated integers: H_ij
Output
* Line 1: A single integer that specifies the number of hilltops
Sample Input
4 3 2 2 1 0 1
3 3 3 2 1 0 1
2 2 2 2 1 0 0
2 1 1 1 1 0 0
1 1 0 0 0 1 0
0 0 0 1 1 1 0
0 1 2 2 1 1 0
0 1 1 1 2 1 0
Sample Output
HINT
Source
题解:为啥我又犯逗比了——明明输入N×M,结果处理时却给我按照N×N了啊啊啊啊啊,害得我光各种WA不说,还纠结了一整天尼玛(phile:无脑的孩纸啊*_*)。。。好啦,除了这个之外,这题还是比较基础的!!!先把所有周围8个点(注意,是8个点,不是4个)中包含比此点高的点统统干掉,然后就可以类比很经典的寻找细胞问题(DFS连通块个数)啦啦啦。。。还有一点,网上不知道那么多逗比(额。。至少我这么看)说应该把所有点从高到低排序然后一个个干,看样子挺好的,但本人实际测试的结果是——网上那样的C++标程VS我的Pascal朴素DFS——50×50时差不多,700×700时,随机0-100的高度,结果我的快1倍左右;700×700,随机0-5的高度,那个程序2s多才出来,我的呵呵呵呵照样0.3s。。。(USACO银组数据居然不卡常数我也是醉了。。。)
const tt:array[..,..] of longint=((,),(,-),(,),(-,),(,),(,-),(-,),(-,-));
var
i,j,k,l,m,n:longint;
a,b:array[..,..] of longint;
c:array[..,..] of longint;
procedure swap(var x,y:longint);inline;
var z:longint;
begin
z:=x;x:=y;y:=z;
end;
procedure sort(l,r:longint);inline;
var i,j,x,y:longint;
begin
i:=l;j:=r;
x:=a[c[(i+j) div ,],c[(i+j) div ,]];
repeat
while a[c[i,],c[i,]]>x do inc(i);
while a[c[j,],c[j,]]<x do dec(j);
if i<=j then
begin
swap(c[i,],c[j,]);
swap(c[i,],c[j,]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
procedure kill(x,y:longint);inline;
var i:longint;
begin
if b[x,y]= then exit;
b[x,y]:=;
for i:= to do
if (a[x+tt[i,],y+tt[i,]]=a[x,y]) and (b[x+tt[i,],y+tt[i,]]=) then kill(x+tt[i,],y+tt[i,]);
end;
function check(x,y:longint):boolean;inline;
var i:longint;
begin
for i:= to do
begin
if a[x+tt[i,],y+tt[i,]]>a[x,y] then exit(false);
end;
exit(true);
end; begin
readln(n,m);
fillchar(b,sizeof(b),);
fillchar(a,sizeof(a),-);
for i:= to n+ do
begin
b[i,]:=;
b[i,m+]:=;
end;
for i:= to m+ do
begin
b[,i]:=;
b[n+,i]:=;
end;
for i:= to n do
begin
for j:= to m do
read(a[i,j]);
readln;
end;
for i:= to n do
begin
for j:= to m do
begin
if b[i,j]= then continue;
if check(i,j)=false then kill(i,j);
end;
end;
for i:= to n do
for j:= to m do
begin
if b[i,j]= then
begin
inc(l);
kill(i,j);
end;
end;
writeln(l);
end.