BZOJ1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场 (BFS)

1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场

Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 661  Solved: 292 [Submit][Status][Discuss]

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.

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

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

Sample Output

3

HINT

   三个山丘分别是:左上角的高度为4的方格,右上角的高度为1的方格,还有最后一行中高度为2的方格.

Source

Silver

[Submit][Status][Discuss] HOME Back\

题目的中文描述的数据范围有问题!

题目的中文描述的数据范围有问题!

题目的中文描述的数据范围有问题!

思路:BFS,我的做法是预处理所有“坏点”,也就是如果点(i,j)的相邻点中有比点(i,j)高的,那么点(i,j)就是坏点。

然后bfs的时候,对于存在一个坏点的联通块(只有数字相同的点能构成一个联通块)都标记成坏点。

然后用左上角开始做bfs…注意遇到坏点跳过但是不要直接标记访问,因为可能之后的点会用到之前的坏点标记自身。

然而因为数据范围有问题wa了好多次。。。

于是看了题解:

大概都是另一种做法(而且都加入了输入挂,不懂,怎么感觉这些人是互相抄的2333)

从最高的点开始做dfs,每次把不大于当前点高度的点都访问掉。。。算作一次访问。

访问次数就是答案。

想了下确实比较巧妙,比较好写,然而比我的写法要慢。

然而窝不懂为什么这种写法数组开小就是返回RE,而我的写法数组开销就是返回WA…

选区_049

我的做法(800ms,bfs):

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年04月03日 星期日 20时01分12秒
  4File Name :code/bzoj/1619.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int dx8[8]={1,1,1,0,0,-1,-1,-1};
 33const int dy8[8]={1,0,-1,-1,1,1,0,-1};
 34const int inf = 0x3f3f3f3f;
 35const int N=705;
 36int h[N][N];
 37bool bad[N][N];
 38int n,m;
 39bool vis[N][N];
 40void checkvis();
 41
 42struct node
 43{
 44    int x,y;
 45
 46    bool inmaze ()
 47    {
 48	if (x>=1&&y>=1&&x<=n&&y<=m)  return true;
 49	return false;
 50    }
 51
 52    void look()
 53    {
 54	cout<<x<<" "<<y<<endl;
 55    }
 56}s;
 57bool ok ( int x,int y)
 58{
 59 //   if (x-1>=1&&h[x-1][y]>h[x][y])  return false;
 60 //   if (x+1<=n&&h[x+1][y]>h[x][y])  return false;
 61 //   if (y-1>=1&&h[x][y-1]>h[x][y])  return false;
 62 //   if (y+1<=m&&h[x][y+1]>h[x][y])  return false;
 63
 64    for ( int i = 0 ; i < 8 ; i++)
 65    {
 66	int nx = x + dx8[i];
 67	int ny = y + dy8[i];
 68	if (nx<1||nx>n||ny<1||ny>m) continue;
 69	if (h[nx][ny]>h[x][y]) return false;
 70    }
 71    return true;
 72}
 73
 74
 75bool bfs( int x,int y)
 76{
 77    queue<node>q;
 78    s.x = x;
 79    s.y = y;
 80    q.push(s);
 81    vis[x][y] = true;
 82    bool res = true;
 83    while (!q.empty())
 84    {
 85	node pre = q.front() ;q.pop();
 86//	pre.look();
 87//	checkvis();
 88	if (!res) bad[pre.x][pre.y] = true;
 89
 90
 91	for ( int i = 0 ; i < 8 ; i++)
 92	{
 93	    node nxt;
 94	    nxt.x = pre.x + dx8[i];
 95	    nxt.y = pre.y + dy8[i];
 96	    if (!nxt.inmaze()) continue;
 97	    if (vis[nxt.x][nxt.y]) continue;
 98	  //  vis[nxt.x][nxt.y] = true;
 99	    if (h[nxt.x][nxt.y]!=h[pre.x][pre.y]) continue;
100	    if (bad[nxt.x][nxt.y])
101	    {
102		res = false;
103	    }
104	    if (!ok(nxt.x,nxt.y))
105	    {
106		res = false;
107	    }
108//	    nxt.look();
109	    q.push(nxt);
110	    vis[nxt.x][nxt.y] = true;
111	}
112    }
113
114    return res;
115
116}
117
118void checkbad()
119{
120    for ( int i = 1 ; i <= n ; i++)
121    {
122	for ( int j = 1 ; j <= m ; j++)
123	{
124	    cout<<bad[i][j]<<" ";
125	}
126	cout<<endl;
127    }
128}
129
130void checkvis()
131{
132    for ( int i = 1 ; i <= n ; i++)
133    {
134	for ( int j = 1 ; j <= m ; j++)
135	{
136	    cout<<vis[i][j]<<" "; 
137	}
138	cout<<endl;
139    }
140}
141int main()
142{
143	#ifndef  ONLINE_JUDGE 
144	freopen("code/in.txt","r",stdin);
145  #endif
146
147	ios::sync_with_stdio(false);
148	cin>>n>>m;
149	for ( int i = 1 ; i <= n ; i++)
150	    for ( int j = 1 ; j <= m ; j++) cin>>h[i][j];
151	ms(bad,false);
152
153	for ( int i = 1 ; i <= n ; i++)
154	{
155	    for ( int j = 1 ; j <= m ; j++)
156	    {
157		if (!ok(i,j)) bad[i][j] = true;
158	    }
159	}
160	ms(vis,false);
161//	checkbad();
162	int ans = 0 ;
163	for ( int i = 1 ; i <= n ; i++)
164	{
165	    for ( int j = 1 ; j  <= m ; j++)
166	    {
167		if (vis[i][j]) continue;
168		if (bad[i][j]) continue;
169		if (bfs(i,j))
170		{
171		    ans++;
172		  //  cout<<i<<" "<<j<<endl;
173		}
174	//	else cout<<"bad:"<<endl;
175	    }
176	}
177
178	cout<<ans<<endl;
179
180
181
182  #ifndef ONLINE_JUDGE  
183  fclose(stdin);
184  #endif
185    return 0;
186}

网上题解的做法(940ms,dfs):

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年04月03日 星期日 21时33分17秒
  4File Name :code/bzoj/r1619.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#include <assert.h>
 20#define fst first
 21#define sec second
 22#define lson l,m,rt<<1
 23#define rson m+1,r,rt<<1|1
 24#define ms(a,x) memset(a,x,sizeof(a))
 25typedef long long LL;
 26#define pi pair < int ,int >
 27#define MP make_pair
 28
 29using namespace std;
 30const double eps = 1E-8;
 31const int dx4[4]={1,0,0,-1};
 32const int dy4[4]={0,-1,1,0};
 33const int dx8[8]={1,1,1,0,0,-1,-1,-1};
 34const int dy8[8]={-1,0,1,1,-1,-1,0,1};
 35const int inf = 0x3f3f3f3f;
 36const int N=705;
 37int n,m;
 38bool vis[N][N];
 39int he[N][N];
 40
 41struct node
 42{
 43    int x,y;
 44    int val;
 45
 46    bool operator < (node b)const
 47    {
 48	return val>b.val;
 49    }
 50}h[N*N];
 51
 52inline int read()
 53{
 54    int x=0,f=1;char ch=getchar();
 55    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 56    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 57    return x*f;
 58}
 59void dfs ( int x,int y)
 60{
 61    vis[x][y] = true;
 62    for ( int i = 0 ; i < 8 ; i++)
 63    {
 64	int nx = x + dx8[i];
 65	int ny = y + dy8[i];
 66
 67	if (nx<1||ny<1||nx>n||ny>m) continue;
 68	if (he[x][y]<he[nx][ny]) continue;
 69	if (vis[nx][ny]) continue;
 70	dfs(nx,ny);
 71    }
 72}
 73int main()
 74{
 75	#ifndef  ONLINE_JUDGE 
 76	freopen("code/in.txt","r",stdin);
 77  #endif
 78
 79	cin>>n>>m;
 80	int cnt = 0 ;
 81	for ( int i = 1 ; i <= n ; i++)
 82	    for ( int j = 1 ; j <= m ; j++)
 83	    {	
 84		    cin>>he[i][j];
 85		    cnt++;
 86		    h[cnt].x = i;
 87		    h[cnt].y = j;
 88		    h[cnt].val = he[i][j];
 89	    }
 90
 91	sort(h+1,h+cnt+1);
 92	ms(vis,false);
 93
 94	int ans = 0 ;
 95	for ( int i = 1 ; i <= cnt ; i++)
 96	{
 97	    int x = h[i].x;
 98	    int y = h[i].y;
 99	    assert(x>=1&&x<N);
100	    assert(y>=1&&y<N);
101	    if (!vis[x][y])
102	    {
103		dfs(x,y);
104		ans++;
105	    }
106
107	}
108
109	cout<<ans<<endl;
110
111  #ifndef ONLINE_JUDGE  
112  fclose(stdin);
113  #endif
114    return 0;
115}