[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;
	}
}


Related Posts