water_堆优化+类dijkstra思想
第一眼,每个格子取决于和他相临的格子,直接枚举O(nm),这么水?!!
第二眼,没那么简单,要找到类似水池的东西,这个池子的边界高度的min才是此格子的高度。为了保证时间复杂度,希望能尽量找到一个格子能被覆盖的最大池子,这样能尽可能地覆盖到别的格子,能近似到一次遍历就出来了,基本O(nm)。
然后。。。发现根本不能找到最大的池子,我的暴力是一层层把小的抬高,O(n^2m^2),QAQ
考虑一个模拟,一格水掉到一个比较高的地上,一定会流到它能流到的最低的地方,这个最低的地方是一个坑,它一定是在类中心位置,也就是说水在一个边界向内流,我们可以不短缩小边界来更新出每个点+积水的高度。维护一个堆,取出最小的,因为一个水池的最终高度是边界高度的最小值。
懵懂。。。
1 #include<bits/stdc++.h>
2 #define MAXN 310
3 using namespace std;
4 inline int maxn(int a,int b){return a>b?a:b; }
5 inline int minn(int a,int b){return a<b?a:b; }
6 int n,m;
7 int ht[MAXN][MAXN];
8 int zui[MAXN][MAXN];
9 int wtr[MAXN][MAXN];
10 struct node{
11 int x,y;
12 friend bool operator <(const node &a,const node &b){
13 return zui[a.x][a.y]>zui[b.x][b.y];
14 }
15 };
16 bool vis[MAXN][MAXN];
17 priority_queue<node >dd;
18 int fx[4][2];
19 int main(){
20 //freopen("da.in","r",stdin);
21 fx[0][0]=0;fx[0][1]=1;
22 fx[1][0]=0;fx[1][1]=-1;
23 fx[2][0]=1;fx[2][1]=0;
24 fx[3][0]=-1;fx[3][1]=0;
25 scanf("%d%d",&n,&m);
26 node tt;
27 for(int i=1;i<=n;++i)
28 for(int j=1;j<=m;++j){
29 scanf("%d",&ht[i][j]);
30 if(ht[i][j]<0)zui[i][j]=0;
31 else zui[i][j]=ht[i][j];
32 }
33 for(int i=1;i<=n;++i)
34 dd.push((node){i,0}),dd.push((node){i,m+1});
35 for(int j=1;j<=m;++j)
36 dd.push((node){0,j}),dd.push((node){n+1,j});
37 int x,y;
38 while(!dd.empty()){
39 node ltop=dd.top();dd.pop();
40 if(vis[x=ltop.x][y=ltop.y])continue;
41 vis[x][y]=1;
42 int ti,tj;
43 for(int k=0;k<4;++k){
44 ti=x+fx[k][0];tj=y+fx[k][1];
45 if(vis[ti][tj])continue;
46 if(ti<1||ti>n)continue;
47 if(tj<1||tj>m)continue;
48 if(zui[ti][tj]<zui[x][y])zui[ti][tj]=zui[x][y];
49 dd.push((node){ti,tj});
50 }
51 }
52 for(int i=1;i<=n;++i){
53 for(int j=1;j<=m;++j)
54 printf("%d ",zui[i][j]-ht[i][j]);
55 puts("");
56 }
57 }