原帖地址
http://bbs.csdn.net/topics/390712018
问题
新的题目又来了,这次还是有关矩阵的。
一个二维数组,向这样。把它想象成一个方格一个方格,数字代表了方格的高度。然后往这些方格里倒水。
当那么高度最低的肯定就可以存住水,问一个m*n的矩阵总共能存多少水。
拿这个矩阵举例子。能存水的肯定就是高度为0的2个点,而他们只能存单位为3的水。因为超过3就是边上的那个3冒出去了。
这个能理解吧。最短板的高度就是存水的高度。这次是只受上下左右4个方格的影响。所以这个矩阵能存水的数量是3+3=6.
9 9 9 9
3 0 0 9
7 8 9 6
再举个例子,这个矩阵能存水的数量就是1.因为只有2的上下左右是3,那么2这个点只能存1个单位的水。
11111
11311
13231
11311
算法就是给定任意m*n的矩阵,计算能存多少水。
代码实现
import java.util.ArrayList; import java.util.List; public class T3 { static int[][] array = { { 9, 9, 9, 9, 9, 10 }, { 9, 2, 2, 3, 11, 11 }, { 7, 2, 9, 12, 1, 20 }, { 7, 6, 3, 1, 11, 13 }, { 9, 9, 6, 9, 9, 14 } }; static int height = array.length; static int width = array[0].length;// 数组宽 static int sum = 0;// 总存储水的量 public static void main(String[] a) throws Exception { int min = 10; int max = 10; int[][] array2 = new int[height][width]; System.out.println("开始矩阵"); for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { array2[i][j]=array[i][j]; System.out.print(array[i][j]); if (array[i][j] < 10) { System.out.print(" ,"); } else { System.out.print(","); } } System.out.println(); } for (int i = 1; i < array.length - 1; i++) {// 寻找最低点 for (int j = 1; j < array[i].length - 1; j++) { if (array[i][j] < min) { min = array[i][j]; } if (array[i][j] > max) { max = array[i][j]; } } } for (int i = min; i < max; i++) { dosum(i); } System.out.println("结束矩阵"); for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j]); if (array[i][j] < 10) { System.out.print(" ,"); } else { System.out.print(","); } } System.out.println(); } System.out.println("节点加水数情况"); for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j]-array2[i][j]); if (array[i][j]-array2[i][j] < 10) { System.out.print(" ,"); } else { System.out.print(","); } } System.out.println(); } System.out.println("总共可以存水:" + sum); } //根据水位点找当前可以加水的点 public static List<List<int[]>> getMin(int shuiwei) { List<List<int[]>> area = new ArrayList<List<int[]>>();// 区域 for (int i = 1; i < array.length - 1; i++) {// 将最小的点加入到数组中作为起始计算的点 for (int j = 1; j < array[i].length - 1; j++) { if (array[i][j] == shuiwei) { int[] point = { i, j }; boolean flag = true; for (int k = 0; k < area.size(); k++) { List<int[]> pointList = area.get(k); if (contains(pointList, point)) { flag = false; break; } } if (flag) { List<int[]> pointList = new ArrayList<int[]>(); pointList.add(point); found(shuiwei, pointList, pointList); area.add(pointList); } } } } return area; } //从一个点出发,查找周边的区域,且区域不包含最外层的点 public static void found(int shuiwei, List<int[]> pointList, List<int[]> allPointList) { List<int[]> pointList2 = new ArrayList<int[]>(); for (int i = 0; i < pointList.size(); i++) { int[] point = pointList.get(i); if(point[0]+1<height-1 && array[point[0]+1][point[1]]==shuiwei){ int[] point2 = {point[0]+1,point[1]}; if(!contains(allPointList, point2)){ pointList2.add(point2); allPointList.add(point2); } } if(point[0]-1>0 && array[point[0]-1][point[1]]==shuiwei){ int[] point2 = {point[0]-1,point[1]}; if(!contains(allPointList, point2)){ pointList2.add(point2); allPointList.add(point2); } } if(point[1]+1<width-1 && array[point[0]][point[1]+1]==shuiwei){ int[] point2 = {point[0],point[1]+1}; if(!contains(allPointList, point2)){ pointList2.add(point2); allPointList.add(point2); } } if(point[1]-1>0 && array[point[0]][point[1]-1]==shuiwei){ int[] point2 = {point[0],point[1]-1}; if(!contains(allPointList, point2)){ pointList2.add(point2); allPointList.add(point2); } } } if(pointList2.size()>0){ found(shuiwei, pointList2, allPointList); }else{ return; } } //做加水的运算 public static void dosum(int shuiwei) { List<List<int[]>> list = getMin(shuiwei); List<List<int[]>> areaList = new ArrayList<List<int[]>>();// 保存新区域 for (int i = 0; i < list.size(); i++) {// 循环区域 List<int[]> pointList = new ArrayList<int[]>();// 保存新点 List<int[]> roundList = new ArrayList<int[]>();// 周边的点 for (int j = 0; j < list.get(i).size(); j++) {// 循环一个区域里的所有点。 int[] point = list.get(i).get(j);// 最低点 int[] pointTop = { point[0] - 1, point[1] }; int[] pointLeft = { point[0], point[1] - 1 }; int[] pointRight = { point[0], point[1] + 1 }; int[] pointBottom = { point[0] + 1, point[1] }; if (pointTop[0]>=0 && !contains(list.get(i), pointTop)) {// 将周边点加入,周边的点可以包括最外层的点 roundList.add(pointTop); } if (pointLeft[1]>=0 && !contains(list.get(i), pointLeft)) { roundList.add(pointLeft); } if (pointRight[1]<width && !contains(list.get(i), pointRight)) { roundList.add(pointRight); } if (pointBottom[0]<height && !contains(list.get(i), pointBottom)) { roundList.add(pointBottom); } } boolean flag = true;// 看周边的点是不是比区域里的点小 for (int j = 0; j < roundList.size(); j++) { int[] round = roundList.get(j); if (array[round[0]][round[1]] <= shuiwei) { flag = false; break; } } if (flag) {// 周边点比区域所有点都大的时候,区域内所有点可以+1 for (int j = 0; j < list.get(i).size(); j++) {// 循环一个区域里的所有点。 int[] point = list.get(i).get(j);// 区域内的点 array[point[0]][point[1]] += 1; sum += 1; pointList.add(point); } if (pointList.size() > 0) { areaList.add(pointList); } } } } //判断数组是否包含点 public static boolean contains(List<int[]> pointList, int[] point) { for (int i = 0; i < pointList.size(); i++) { if (pointList.get(i)[0] == point[0] && pointList.get(i)[1] == point[1]) { return true; } } return false; } }