二维直方图盛水

来源:互联网 发布:微信飞机大战源码 编辑:程序博客网 时间:2024/04/28 14:49
基本思路:用两个数据结构1. visited matrix 表明已经用过的cell2. PriorityQueue放目前的边界PQ总是弹出最低的cell。得到最低的cell以后找没有访问过的邻居。如果邻居小的话,就可以装水了。把邻居放入PQ中作为新的边界(如果邻居低的话,用当前height代替邻居的高度)。这样一直到PQ为空。复杂度N*N*logN, 程序不是很复杂。class waterContainer{    private int m;    private int n;    private int[][] mat;    private boolean[][] visited;    private PriorityQueue<Cell> pq;    private int count;        class Cell implements Comparable<Cell>{        int x;        int y;        int height;        public Cell(int x,int y,int height){            this.x=x;            this.y=y;            this.height=height;        }                public int compareTo(Cell o){            return height-o.height;        }    }        public waterContainer(int[][] input){        mat=input;        m=mat.length;        n=mat[0].length;        visited=new boolean[m][n];        pq=new PriorityQueue<Cell>();        count=0;    }        private void check(int x, int y, int lowest){        if(x<0 || x>=m || y<0 || y>=n || visited[x][y]) return;        if(mat[x][y]<lowest) count+=lowest-mat[x][y];        visited[x][y]=true;        pq.offer(new Cell(x,y,Math.max(lowest, mat[x][y])));    }        public int solve(){        for(int i=0;i<m;i++){            visited[i][0]=true;            pq.offer(new Cell(i,0,mat[i][0]));                            visited[i][n-1]=true;            pq.offer(new Cell(i,n-1,mat[i][n-1]));        }                for(int j=1;j<n-1;j++){            visited[0][j]=true;            pq.offer(new Cell(0,j,mat[0][j]));                            visited[m-1][j]=true;            pq.offer(new Cell(m-1,j,mat[m-1][j]));        }        while(!pq.isEmpty()){            Cell curr=pq.poll();            check(curr.x-1,curr.y,curr.height);            check(curr.x+1,curr.y,curr.height);            check(curr.x,curr.y-1,curr.height);            check(curr.x,curr.y+1,curr.height);        }                return count;    }}