http://acm.pku.edu.cn/JudgeOnline/problem?id=2227

    《算法艺术与信息学竞赛》一书例题(p89) , 挺不错的一道题。

    能存储的水的量主要取决于最低的位置的高度,而且边缘是不能注水的。所以可以从边缘中找出一个最低点,然后对其四周进行操作,有两种情况:

    1、旁边的格子高度比其大,这个时候就要将这个格子标记为不能注水,如果注水,则会流出,这个格子旁边的格子若比他大也需标记不能注水

    2、旁边的格子高度比其小,此时可以注入水达到两个格子的水量相同,由于我们事先选取了最低的格子,所以这个水必定不会流出,同理还要对这个水周围比其高度大的格子进行标志。

    由于每次都需要找最低的格子进行覆盖,所以要用到优先队列来进行优化,由于每个格子最多进队一次,所以时间复杂度为O( nmlog(nm) )

代码
1 #include <iostream>
2 #include <queue>
3 #include <vector>
4 #include <algorithm>
5  using namespace std;
6
7 const int maxn = 301;
8
9 typedef __int64 LL;
10
11 int W, H, hash[maxn][maxn];
12 LL bowl[maxn][maxn], A , B;
13 struct NODE { LL r, c, h; } T;
14
15 struct cmp {
16 bool operator () (const NODE a, const NODE b) const {
17 return a.h > b.h;
18 }
19 };
20 priority_queue<NODE , vector<NODE> , cmp> que;
21
22 int move[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
23
24 void cover(LL r , LL c, LL h) //覆盖周围比其高的格子
25 {
26 for(int i=0; i < 4; i++) {
27 LL x = r + move[i][0];
28 LL y = c + move[i][1];
29 if(x <= 0 || y <= 0 || x > H || y > W || hash[x][y] || bowl[x][y] < h)
30 continue;
31 NODE tmp;
32 tmp.r = x , tmp.c = y , tmp.h = bowl[x][y];
33 hash[x][y] = 1;
34 que.push( tmp );
35 cover(x , y , tmp.h);
36 }
37 }
38
39 void floodfill(LL r , LL c, LL h) //注入水
40 {
41 for(int i=0; i < 4; i++) {
42 LL x = r + move[i][0];
43 LL y = c + move[i][1];
44 if(x <= 0 || y <= 0 || x > H || y > W || hash[x][y] || bowl[x][y] > h)
45 continue;
46 NODE tmp;
47 tmp.r = x , tmp.c = y , tmp.h = h;
48 bowl[x][y] = h;
49 hash[x][y] = 1;
50 que.push( tmp );
51 floodfill(x , y , h);
52 cover(x , y , h);
53 }
54 }
55
56 void init() //初始将边缘不能注水的格子推入优队
57 {
58 for(int i=1; i <= W; i++)
59 {
60 T.r = 1 , T.c = i , T.h = bowl[1][i];
61 hash[1][i] = 1;
62 que.push(T);
63 T.r = H , T.c = i , T.h = bowl[H][i];
64 hash[H][i] = 1;
65 que.push(T);
66 }
67
68 for(int i=1; i <= H; i++)
69 {
70 T.r = i , T.c = 1 , T.h = bowl[i][1];
71 hash[i][1] = 1;
72 que.push(T);
73 T.r = i , T.c = W , T.h = bowl[i][W];
74 hash[i][W] = 1;
75 que.push(T);
76 }
77 }
78
79 void solve()
80 {
81 LL r , c , h;
82 while(!que.empty())
83 {
84 r = que.top().r , c = que.top().c , h = que.top().h , que.pop();
85 floodfill( r , c , h );
86 cover( r , c , h );
87 }
88 for(int i=1; i <= H; i++)
89 for(int j=1; j <= W; j++)
90 B += bowl[i][j];
91 printf("%I64d\n", B - A);
92 }
93
94 int main()
95 {
96 A = B = 0;
97 scanf("%d %d", &W, &H);
98 for(int i=1; i <= H; i++) {
99 for(int j=1; j <= W; j++) {
100 scanf("%I64d", &bowl[i][j]);
101 A += bowl[i][j];
102 }
103 }
104 init();
105 solve();
106 return 0;
107 }
108

 

posted on 2010-05-23 01:08  xIao.wU 思维磁场  阅读(506)  评论(0编辑  收藏  举报