Title Description
Xiaoyi came to a stone road, each stone from 1 next to the number: 1, 2, 3
This flagstone road can only advance according to special rules: for the flagstone whose number is k, Xiaoyi can only jump forward one divisor step of K (excluding 1 and K) at a time, that is, jump to the position of K+X(X is a non-1 and its own divisor of K). Xiaoyi is currently on the slate numbered N. he wants to jump to the slate numbered M. Xiaoyi wants to know how many times he needs to jump to get there
For example:
N = 4,M = 24:
4->6->8->12->18->24
So Xiaoyi needs to jump at least 5 times to jump from No.4 slate to No.24 slate
Input Description: the input is one line, with two integers n, m, separated by spaces. (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)
Output Description: output the minimum number of steps that Xiaoyi needs to jump, if it can't reach output-1
AC solution (one dimensional dynamic gauge):
We use dynamic programming to solve this problem. First of all, we notice that according to the conditions in the problem: (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000), if we use a two-dimensional table for dynamic planning, the time and space limit will be exceeded. Therefore, we should establish and maintain a one-dimensional table for dynamic regulation operation
Establish and maintain a one-dimensional table dp with length of M+1. dp[i] records the minimum steps from n slate to I slate, initializes dp[n] to 0, and the rest values are max.max "value. Traverse and update the DP table from n: if dp[i] = = math.max ﹣ value, it means that it is not reachable from n to I, skip and continue the cycle; if dp[i]! = math.max ﹣ value, it means that it is reachable from n to I, find the divisor of I for dynamic planning, and the state transition equation is:
dp[i+j]=min(dp[i]+1,dp[i+j]) // i%j==0(j is the divisor of i) and i + J < = m dp[n]=0 // Step 0 from n to n itself
Full code:
import java.util.Scanner; import java.lang.Math; import java.lang.Integer; public class Main { public static void main(String[] args) { Scanner input=new Scanner(System.in); int n=input.nextInt(); int m=input.nextInt(); if(n==m) { System.out.println(0); return; } int[] dp=new int[m+1]; //For the record table of dynamic gauge, dp[i] records the minimum steps from n stone slab to I stone slab, which is not reachable when dp[i]=Integer.MAX_VALUE for(int i=0;i<=m;i++) { dp[i]=Integer.MAX_VALUE; } dp[n]=0; for(int i=n;i<m;i++) { if(dp[i]==Integer.MAX_VALUE) //Unreachable { continue; } for(int j=2;(j*j)<=i;j++) { if(i%j==0) //j is the divisor of i { if(i+j<=m) { dp[i+j]=Math.min(dp[i+j],dp[i]+1); } if(i+(i/j)<=m) { dp[i+(i/j)]=Math.min(dp[i+(i/j)],dp[i]+1); } } } } if(dp[m]==Integer.MAX_VALUE) { System.out.println(-1); } else { System.out.println(dp[m]); } } }
Time complexity: traverse the one-dimensional linear table once, the divisor of elements is approximately n/2, so it needs to calculate about n*(n/2) times, and the time complexity is O(n2)
Spatial complexity: establish a linear dynamic table, O(n)
In addition to the above mentioned method of determining the dimensions of the dynamic gauge table according to the data value range, there is another noteworthy point in this solution: in general, the state transition equation, for example, dp[i][j]=min(dp[i][j],dp[i+k][j]) or dp[i][j]=max(dp[i][j],dp[i+k][j]) is to calculate and update dp[i][j] according to the values of other positions in the table when traversing dp[i][j]; while the state transition equation of this problem: dp[i+k]=min(dp[i]+1,dp[i+k]) is to calculate and update dp[i+k] according to the existing values of dp[i] when traversing dp[i]
Here are two solutions that the author did not pass in the process of solving the problem. They are able to calculate the correct answer, but beyond the time and space limit
Solution one without AC (two dimensional dynamic gauge)
Establish and maintain a two-dimensional table dp[i][j] to store the minimum number of steps from No. I to No. j slate. dp[i][j]=-1 means that it is not reachable from I to j. The equation of state transition is as follows:
dp[i][j]=min(dp[i][j],dp[i+k][j]) //1<k<i,i%k,i!=j,dp[i+k][j]!=-1 dp[i][j]=0 //i==j
Full code:
import java.util.Scanner; import java.lang.Math; import java.lang.Integer; public class Main { public static void main(String[] args) { if(n==m) { System.out.println(0); return; } int[][] dp=new int[m+1][m+1]; //Record sheet for dynamic gauge, dp[i][j] represents the minimum number of steps from No. I slate to No. j slate for(int i=n;i<m;i++) { dp[i][i+1]=-1; } for(int l=2;l<=(m-n);l++) //Distance from start number to target number { for(int i=n;i<=(m-l);i++) //Initial number { int j=i+l; //Target number int temp=Integer.MAX_VALUE; for(int k=2;k<Math.min(i,l+1);k++) { if(i%k==0 && dp[i+k][j]!=-1) //k is the divisor of i, and the method of jumping k step from i can reach { temp=Math.min(temp,1+dp[i+k][j]); } } if(temp==Integer.MAX_VALUE) { dp[i][j]=-1; } else { dp[i][j]=temp; } } } System.out.println(dp[n][m]); } }
Time complexity: it needs to traverse the two-dimensional table. The divisor of elements is approximately n/2, so it is O(n3)
Spatial complexity: establish and maintain a two-dimensional table, so it is O(n2)
This solution can calculate the correct answer, but it can't AC. In test case n=8,m=85678, the program throws java.lang.OutOfMemoryError: Java heap space. The instance storage space of array in JVM is in heap. When m=85678, the dp[m+1][m+1] created is too large to cause heap overflow Error. Space limit not met
No AC solution II (another dynamic gauge + greed):
Establish a dynamic table dp, which is implemented by two-dimensional ArrayList. dp[s] stores the number of slate that needs at least step s to step M. It is known that it takes 0 steps for m-stone slab to reach its own, traversing from m-1 to N. for i-stone slab (n = < I < = m), the minimum number of steps it takes to reach m is the minimum number of steps it can take to reach m-stone slab in one step + 1 (greed), and the stone slab that cannot reach m-stone slab does not need to be stored.
State transfer equation:
step[i]=min(s|j∈dp[s],i+k=j,i%k==0) //i!=m step[i]=0 //i==m
Full code:
import java.util.Scanner; import java.lang.Math; import java.lang.Integer; import java.util.ArrayList; public class Main { public static void main(String[] args) { if(n==m) { System.out.println(0); return; } ArrayList<ArrayList<Integer>> stepNumTable=new ArrayList<>(); //Record the number of the stone slab that can reach No. m in at least x steps for(int i=0;i<m-n;i++) { stepNumTable.add(new ArrayList<>()); } stepNumTable.get(0).add(m); //m reaches 0 step of itself for(int i=m-2;i>=n;i--) { int step=-1; for(int s=0;s<=(m-i);s++) //S is the minimum available s steps to m stone slab { for(int j=0;j<stepNumTable.get(s).size();j++) { int diff=stepNumTable.get(s).get(j)-i; //Hop count if(i%diff==0 && diff!=1 && diff<i) //Step diff is the divisor of i { step=s+1; //At least step=s+1 to m is required for i stone slab break; } } if(step!=-1) { stepNumTable.get(step).add(i); if(i==n) { System.out.println(step); return; } break; } } } System.out.println(-1); } }
Time complexity: O(n2)
Spatial complexity: O(n)
There will be no heap overflow Error, but it still exceeds the time limit