Fire Air(华科校赛 网络赛)

题目

原题链接:https://www.nowcoder.com/acm/contest/106/L

在100000 * 10000的空地上,有n个时间点,每个时间点会在(xi,yi)上种一棵树。

定义绿色:被树包围的空地的个数。

问每个时间点之后绿色为多少。如图:

思路

逆向求解,从(0,0)位置将圈外的全标记(给空地加一圈),在分别考虑当前的树,是在圈内还是圈的外围。

由于vis是全局数组,之后的bfs都非常快,每个点只遍历过一次。

代码实现

 1 #include<stdio.h>
 2 #include<queue>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 typedef pair<int, int> P;
 7 const int maxn = 100000 + 10;    //点的最大个数
 8 const int SIZE = 2000 + 10;        //地图大小
 9 const int offset = 1000;        //偏置
10 const int dx[] = { -1,0,1,0 };
11 const int dy[] = { 0,1,0,-1 };
12 int n,xi[maxn],yi[maxn],ans[maxn];
13 bool vis[SIZE][SIZE], maze[SIZE][SIZE];
14 
15 int bfs(int x, int y)
16 {
17     int ret = 0;
18     queue<P>q;
19     vis[x][y] = true;
20     q.push(P(x, y));
21     while (!q.empty())
22     {
23         P p = q.front(); q.pop();
24         ret++;
25         for (int i = 0; i < 4; i++)
26         {
27             int nx = p.first + dx[i], ny = p.second + dy[i];
28             if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE && (!vis[nx][ny]))
29             {
30                 vis[nx][ny] = true;
31                 q.push(P(nx, ny));
32             }
33         }
34     }
35     return ret;
36 }
37 
38 int main()
39 {
40     scanf("%d", &n);
41     for(int i = 1;i <= n;i++)
42     { 
43         scanf("%d%d", &xi[i], &yi[i]);
44         maze[xi[i] + offset][yi[i] + offset] = 1;
45         vis[xi[i] + offset][yi[i] + offset] = 1;
46     }
47 
48     bfs(0, 0);
49     int res = 0;
50     for (int i = 0; i < SIZE; i++)
51         for (int j = 0; j < SIZE; j++)
52             if (vis[i][j] == false)  res++;
53     ans[n] = res;
54 
55     for (int i = n; i >= 4; i--)  //1~3棵以内不可能围成空地
56     {
57         int u = xi[i] + offset;
58         int v = yi[i] + offset;
59         maze[u][v] = 0;  
60         int cnt = 0;
61         for (int j = 0; j < 4; j++)
62         {
63             int nu = u + dx[j], nv = v + dy[j];
64             if (maze[nu][nv] == 0 && vis[nu][nv] == 1)  cnt++;
65         }
66         if (cnt == 0)   //cnt == 0,表示该点在内部
67         {
68             vis[u][v] = 0;
69             res++;
70         }
71         else res -= (bfs(u, v) - 1);
72         ans[i - 1] = res;
73     }
74     for (int i = 1; i <= n; i++)
75         printf("%d\n", ans[i]);
76     return 0;
77 }

参考链接:https://www.nowcoder.com/acm/contest/view-submission?submissionId=26038731

猜你喜欢

转载自www.cnblogs.com/lfri/p/9781223.html
今日推荐