1) Problem description
Polygon game is a game played by one person. At the beginning, there is a polygon composed of n vertices. Each vertex is assigned an integer value, and each edge is assigned an operator + or *. All the edges are numbered from 1 to N in turn. In step 1 of the game, delete one edge.
The next n-1 steps are as follows:
(1) Select an edge e and two vertices V1 and V2 connected by E;
(2) Replace edge e with a new vertex and two vertices V1 and V2 connected by E. The integral values of vertices V1 and V2 are assigned to the new vertex through the operation on edge E.
Finally, all sides are removed (disconnected) and the game is over. The score of the game is the integer value on the remaining vertex. Problem: for a given polygon, calculate the highest score.
2) Code implementation
package hello; import java.util.HashMap; import java.util.Scanner; import java.util.Stack; public class fuck { private int n; //Polygon sides private char[] op; //Corresponding operation of each edge (counting from 1) private int[] v; //Value per vertex (count from 1) private long[][][] m; //m[i][n][1]: represents the maximum value that can be obtained by deleting the i-th edge and the n-th chain (including n vertices) at the beginning //m[i][n][0]: represents the minimum value that can be obtained by deleting the i-th edge of the chain with length of N at the beginning private int[][][] cut; //cut[i][j][0]; indicates the position where the chain m[i][j][0] breaks when it reaches the minimum value //cut[i][j][1]: indicates the position where the m[i][j][1] chain breaks when it reaches the maximum value private Stack<Integer> stack; //Use stack to save the order of merging edges private int firstDelEdge; //Record the first deleted edge in the best case private long bestScore; //Record the best score //Initialization public fuck(int n, long[][][] m, char[] op, int[] v){ this.n = n; this.m = m; this.op = op; this.v = v; this.cut = new int[n+1][n+1][2]; this.stack = new Stack<>(); } //************************************************************************************************************************************ /** * Subfunction * Serving the main executive function is the encapsulation of some methods of the main function */ //Encapsulate the maximum value and the minimum value when the broken edge is * or + to expose a unified method private HashMap<String, Long> minMax(int i, int s, int j, HashMap<String, Long> resMap){ int r = (i+s-1) % n + 1; long a = m[i][s][0], b = m[i][s][1], c = m[r][j-s][0], d = m[r][j-s][1]; if(op[r] == '+'){ resMap.put("minf", a+c); resMap.put("maxf", b+d); }else{ long[] e = new long[]{0, a*c, a*d, b*c, b*d}; long minf = e[1], maxf = e[1]; for (int k = 2; k < 5; k++){ if(minf > e[k]) minf = e[k]; if(maxf < e[k]) maxf = e[k]; } resMap.put("minf", minf); resMap.put("maxf", maxf); } return resMap; } /** * Obtain the optimal merging sequence and store it in the stack * @param i Indicates which vertex the sub chain starts from * @param j Length of the sub chain (for example, j=2, indicating that there are two vertices in the chain) * @param needMax Whether to take the maximum value of the chain. If the incoming value is false, take the minimum value of the sub chain */ //Calculate the point to be disconnected when the sub chain m[i][j][1(0)] reaches the maximum (small) value, and press the stack, and press the stack when necessary. //Recursively stack to child chain length is 1 (i.e. when j is 1). private void getBestSolution(int i, int j, boolean needMax){ //If needMax is true, it means the point stack to be disconnected when taking the maximum value of the sub chain. If it is false, it means the point stack to be disconnected when taking the minimum value of the sub chain int s,r; if(j == 1){ //There is only one vertex in the chain, directly return }else if(j == 2){ s = cut[i][j][1]; r = (i+s-1) % n + 1; //Because the r of the stack i s relative to the beginning, and S is relative to I. stack.push(r); }else { //When there are more than two vertices in the chain, the optimal edge is pushed into the stack s = needMax ? cut[i][j][1] : cut[i][j][0]; r = (i+s-1) % n + 1; stack.push(r); //Recursive operation when J > 2 if(this.op[r] == '+'){ //When the consolidation calculation is a "+" operation if(needMax){ //If the merged parent chain needs to get the maximum value getBestSolution(i, s, true); getBestSolution(r, j-s, true); }else { //If the merged parent chain needs to get the minimum value getBestSolution(i, s, false); getBestSolution(r, j-s, false); } }else{ //When the consolidation calculation is a "*" operation long a = m[i][s][0], b = m[i][s][1], c = m[r][j-s][0], d = m[r][j-s][1]; long[] e = new long[]{0, a*c, a*d, b*c, b*d}; long mergeMax = e[1], mergeMin = e[1]; for(int k=2; k<=4; k++){ if(e[k] > mergeMax) mergeMax = e[k]; if(e[k] < mergeMin) mergeMin = e[k]; } long merge = ((needMax) ? mergeMax : mergeMin); //Determine whether the merged parent chain is the largest or the smallest if(merge == e[1]){ //Sub chain 1 and sub chain 2 are the minimum getBestSolution(i, s, false); getBestSolution(r, j-s, false); }else if(merge == e[2]){ //Take the minimum for sub chain 1 and the maximum for sub chain 2 getBestSolution(i, s, false); getBestSolution(r, j-s, true); }else if(merge == e[3]){ //Sub chain 1 takes the maximum and sub chain 2 takes the minimum getBestSolution(i, s, true); getBestSolution(r, j-s, false); }else { //Sub chain 1 and sub chain 2 take the maximum getBestSolution(i, s, true); getBestSolution(r, j-s, true); } } } } //************************************************************************************************************************************ /** * Main executive function * Is the core of the main algorithm */ //Find out which point is the most disconnected and fill the most in m[i][j][0] and m[i][j][1]; fill the disconnected point in cut[i][j][0] and cut[i][j][1] private void polyMax(){ //1 fill in forms m[i][j][0] and m[i][j][1] and cut[i][j][0] and cut[i][j][1] HashMap<String, Long> resMap = new HashMap<>(); for (int j = 2; j <= n; j++){ //Length of chain for(int i = 1; i<= n; i++){ //When the i-th edge is disconnected at the beginning m[i][j][0] = Long.MAX_VALUE; m[i][j][1] = Long.MIN_VALUE; for(int s = 1; s < j; s++){ //Disconnected position resMap = this.minMax(i, s, j, resMap); if(m[i][j][0] > resMap.get("minf")){ m[i][j][0] = resMap.get("minf"); cut[i][j][0] = s; //Record the breakpoint of the minimum value of the chain } if(m[i][j][1] < resMap.get("maxf")){ m[i][j][1] = resMap.get("maxf"); cut[i][j][1] = s; //Record the breakpoint where the chain gets the maximum value } } } } //2 according to table m, calculate the maximum value when the first disconnection occurs, and output some relevant data bestScore = m[1][n][1]; firstDelEdge = 1; //Initially broken edge, initialized to first edge for (int i = 2; i <= n; i++){ if(bestScore < m[i][n][1]){ bestScore = m[i][n][1]; firstDelEdge = i; //Update if there is a better result at the beginning of breaking the i-th edge } } System.out.print("\n"); System.out.println("At first disconnect the i The maximum value that can be formed when the strip is edge:"); for(int i=1; i<=n; i++){ //The maximum score that can be obtained by breaking the i-th edge at the beginning System.out.println("i=" + i + " " + m[i][n][1]); } System.out.print("\n"); System.out.println("[The first edge that should be broken is: firstDelEdge=" + firstDelEdge+"]"); //3 use getBestSolution method to calculate the disconnection sequence when the maximum value is reached and output System.out.print("\n"); getBestSolution(firstDelEdge, n, true); //Press the points to be disconnected when the sub chain m[firstDelEdge][n] wants to take the maximum value in sequence. System.out.println("To get the maximum number of disconnects:"); System.out.println("stack--> "+ firstDelEdge); while (!stack.empty()){ //Print the optimal merge order after the first deledge is broken System.out.println("stack--> " + String.valueOf(stack.pop())); } System.out.print("\n"); System.out.println("[The number (maximum value) obtained after the above disconnection sequence is: BestScore=" + bestScore+"]"); } //************************************************************************************************************************************ /** * Main function * @param args */ public static void main(String[] args){ System.out.println("Please enter the number of edges (points) you want to enter:"); Scanner scanner = new Scanner(System.in); while(scanner.hasNext()){ //1 input stream int n = scanner.nextInt(); long[][][] m = new long[n+1][n+1][2]; char[] op = new char[n+1]; int[] v = new int[n+1]; System.out.print("\n"); System.out.println("Please enter edge and point:"); for(int i=1; i<=n; i++){ //i starts at 1. op[i] = scanner.next().charAt(0); v[i] = scanner.nextInt(); } //2 initialization fuck ploygonAgent = new fuck(n, m, op, v); for (int i=1; i<=n; i++){ //Initialize the first column of m[i][j][0] and m[i][j][1] m[i][1][0] = m[i][1][1] = v[i]; } //3 main executive function ploygonAgent.polyMax(); } scanner.close(); } }
Please enter the number of edges (points) you want to enter: 5 //Please enter edge and point: * -5 + -2 * -8 * -5 + 8 //The maximum value that can be formed when the i-th edge is disconnected at the beginning: i=1 168 i=2 480 i=3 488 i=4 488 i=5 120 [The first edge that should be broken is: firstDelEdge=3] //To get the maximum number of disconnects: stack--> 3 stack--> 2 stack--> 1 stack--> 5 stack--> 4 [The number (maximum value) obtained after the above disconnection sequence is: BestScore=488]
3) Time complexity and space complexity
Time complexity:
O(n*3)
[the main time complexity lies in the three for's filled in the form]
Spatial complexity:
O(n*2)