[Water Pen] An algorithm problem I saw many years ago, take a souvenir
Original post address
http://bbs.csdn.net/topics/390712018
question
Here comes a new topic, this time it's about matrices.
A 2D array, like this. Think of it as a square by square, with the numbers representing the height of the squares. Then pour water into these squares.
When the one with the lowest height can definitely hold water, ask how much water a m*n matrix can hold in total.
Take this matrix as an example. The ones that can store water must be 2 points with a height of 0, and they can only store water with a unit of 3. Because more than 3 is the 3 on the side that pops out.
This can be understood. The height of the shortest board is the height of the water storage. This time it is only affected by 4 squares up, down, left and right. So the amount of water that this matrix can store is 3+3=6.
9 9 9 9
3 0 0 9
7 8 9 6
For another example, the amount of water that this matrix can store is 1. Because only the upper, lower, left and right sides of 2 are 3 , then the point 2 can only store 1 unit of water.
The 11111
11311
13231
11311
algorithm is to give an arbitrary m*n matrix and calculate how much water can be stored.
Code
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;//Array width static int sum = 0;// The total amount of stored water public static void main(String[] a) throws Exception { int min = 10; int max = 10; int[][] array2 = new int[height][width]; System.out.println("Start Matrix"); 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++) {// find the lowest point 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("End matrix"); 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("The number of water added to the node"); 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("Total water can be stored: " + sum); } / / Find the current point where water can be added according to the water level point 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++) {// Add the smallest point to the array as the starting point for the calculation 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; } //Start from a point, find the surrounding area, and the area does not contain the outermost point 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; } } // do the operation of adding water 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++) {// loop area List<int[]> pointList = new ArrayList<int[]>();// 保存新点 List<int[]> roundList = new ArrayList<int[]>();// surrounding points for (int j = 0; j < list.get(i).size(); j++) {// Loop through all points in a region. int[] point = list.get(i).get(j);// lowest point 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)) {// Add the surrounding points, the surrounding points can include the outermost points 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;// See if the surrounding points are smaller than the points in the area 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) {// When the surrounding points are larger than all the points in the area, all points in the area can be +1 for (int j = 0; j < list.get(i).size(); j++) {// Loop through all points in a region. int[] point = list.get(i).get(j);// point in the area array[point[0]][point[1]] += 1; sum += 1; pointList.add(point); } if (pointList.size() > 0) { areaList.add(pointList); } } } } //Check if the array contains a point 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; } }