小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
例如:
N = 4,M = 24:
4->6->8->12->18->24
于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板
输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)
输出小易最少需要跳跃的步数,如果不能到达输出-1
4 24
5
/**
* Created by arrow on 11/19/17.
*/
public class Question {
public static int jumpTimes(int N, int M) {
// jump数组表示调到jump[i]所用的最大步数
int[] jump = new int[M + 1];
// 初始化jump数组为-1
for (int i = N; i <= M; ++i) {
jump[i] = -1;
}
int step = 1;
jump[N] = 0;
// printState(jump, N);
while (jump[M] == -1) {
int max_step = Integer.MIN_VALUE;
for (int cur = N; cur <= M; ++cur) {
if (jump[cur] > max_step)
max_step = jump[cur];
if (jump[cur] < step - 1)
continue;
// 找到step-1步所能走到的石板
else if (jump[cur] == step - 1) {
for (int k = 2; k <= Math.sqrt(cur); ++k) {
// System.out.println("cur = " + cur + ", k = " + k);
// 找到约数k,更新jump数组
if (cur % k == 0) {
if (cur + k <= M && jump[cur + k] == -1) jump[cur + k] = step;
if (cur + cur / k <= M && jump[cur + cur / k] == -1) jump[cur + cur / k] = step;
}
}
} else {
continue;
}
}
// 当前步数和jump数组中最大的步数相差2,
// 等价于是找不到step-1步所能走到的石板了,因为越界了,所以循环结束
if (step - max_step > 1)
break;
step++;
// printState(jump, N);
}
// printState(jump, N);
return jump[M];
}
// 打印状态数组
private static void printState(int[] jump, int N) {
System.out.println("JUMP");
for (int i = N; i < jump.length; ++i) {
System.out.printf("%5d ", i);
}
System.out.println();
for (int i = N; i < jump.length; ++i) {
System.out.printf("%5d ", jump[i]);
}
System.out.println();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int result = jumpTimes(N, M);
System.out.println(result);
}
}
广度优先搜索,同时搜过的点不再搜,肯定步数比上一次搜索要大。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
Queue<Integer> queue = new LinkedList<Integer>();
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
ArrayList<Integer> factor = new ArrayList<Integer>();
queue.add(n);
map.put(n, 0);
int i,j;
while(!queue.isEmpty()) {
int head = queue.poll();
factor = getAppNums(head);
if(head == m) {
System.out.print(map.get(head));
return;
}
for(i=0;i<factor.size();i++) {
if(!map.containsKey(head+factor.get(i)) && head+factor.get(i)<=m) {
queue.add(head+factor.get(i));
map.put(head+factor.get(i), map.get(head)+1);
}
}
}
System.out.print(-1);
}
public static ArrayList<Integer> getAppNums(int n) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
list.add(i);
if (n / i != i) {
list.add(n / i);
}
}
}
return list;
}
}
#include <stdio.h>
#include <vector>
#include <iostream>
#include <memory.h>
#include "math.h"
using namespace std;
void findYueShu(int x,vector<int> &a){
for(int i = 2;i<=(int)sqrt((double)x);++i){
if(x%i == 0){
a.push_back(i);
if(x/i != i)
a.push_back(x/i);
}
}
}
int main(){
int n,m;
while(cin>>n>>m){
//动态规划
int* buf = new int[m+1];
memset(buf,0,sizeof(int)*(m+1));
buf[n] = 1;
for(int i = n;i<m;++i){
//找到i所对应的约数容器
if(buf[i] == 0)
continue;
vector<int> yueshu;
findYueShu(i,yueshu);
for(auto it = yueshu.begin();it!=yueshu.end();++it){
if((i+*it)<=m){
if(buf[i+*it] != 0)
//发生冲突
buf[i+*it] = min(buf[i+*it],buf[i]+1);
else
buf[i+*it] = buf[i]+1;
}
}
}
if(buf[m] == 0)
cout<<-1<<endl;
else
cout<<buf[m]-1<<endl;
delete[] buf;
}
}
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define INT_MAX 100001
int main()
{
int n, m;
while(cin >> n >> m)
{
vector<int> dp(m + 1, INT_MAX); //dp[i]为在第i个石板时,所需要的步数,初始设为条件范围内的最大值
dp[n] = 0;
for (int i = n; i <= m; i++)
{
for (int j = 2; j*j <= i; j++) //比如i为8,当找到i的一个约数j为2时,另一个约数就为i/j
{ //所以只需要找j*j<=i,事实上如果不这样做,部分用例运行超时
if (i%j == 0)
{
if (i + j <= m)
dp[i + j] = min(dp[i + j],dp[i]+1);
if(i+i/j<=m) //关键步骤
dp[i + i/j] = min(dp[i + i/j],dp[i]+1);
}
}
}
if(dp[m]==INT_MAX)
cout<<"-1"<<endl;
else
cout<<dp[m]<<endl;
}
} 枚举一般位置的情况,到达位置时,可以再往右走
的约数步(除开1和
本身),直到抵达终点
时更新最小步数就好,如果当前位置
超过
了,表明本次的跳跃策略是无效的。
整个尝试的逻辑非常简单,但我们可能反复到达某个位置,而这个位置在第二次到达的时候,我们并没有必要重复计算从它到终点需要的最少步数(如果从它根本不可能到终点,那就更没有必要继续递归展开)。因此可以加个缓存表记录已经计算过的结果,从而避免重复递归展开计算。
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] params = br.readLine().split(" ");
int n = Integer.parseInt(params[0]), m = Integer.parseInt(params[1]);
int[] dp = new int[m + 1];
Arrays.fill(dp, -1);
int ans = dfs(n, m, dp);
System.out.println(ans == Integer.MAX_VALUE? -1: ans);
}
private static int dfs(int cur, int end, int[] dp) {
if(cur == end){
return 0; // cur=end时还需要0步到达终点
}else{
if(dp[cur] != -1 || dp[cur] == Integer.MAX_VALUE){
return dp[cur]; // -1表示还没算过,得算;整数最大值表示到不了,直接返回;其他正数表示已经有结果了,直接返回。
}
int pNext = Integer.MAX_VALUE;
// 当前位置是cur,尝试所有能走的步数
for(int i = 2; i <= (int)Math.sqrt(cur); i++){
if(cur % i == 0){
// 计算后续还有几步能到终点
if(cur + i <= end){
pNext = Math.min(pNext, dfs(cur + i, end, dp));
}
if(cur / i != i && cur + cur/i <= end){
pNext = Math.min(pNext, dfs(cur + cur/i, end, dp));
}
}
}
if(pNext != Integer.MAX_VALUE){
dp[cur] = 1 + pNext; // 能到就加一步
}else{
dp[cur] = pNext; // 返回最大值表示到不了
}
return dp[cur];
}
}
}根据这个递归的做法,还可以进一步优化为动态规划版本。但如果笔试时赶时间,建议就直接提交记忆化搜索的版本,一般情况下复杂度与动态规划相同。
#include<iostream>
using namespace std;
#include<vector>
#include<limits.h>
#include<math.h>
void getDiv(int x,vector<int>& a)
{
for(int i=2;i<=sqrt(x);++i)
{
if(x%i == 0)
{
a.push_back(i);
if(x/i != i)
a.push_back(x/i);
}
}
}
int getMinStep(int n,int m)
{
vector<int> step(m+1,INT_MAX);
//初始化
step[n] = 0;
for(int i=n;i<m;++i)
{
if(step[i]==INT_MAX)
continue;
vector<int> a;
getDiv(i,a);
for(int j=0;j<a.size();++j)
{
if(i+a[j]<=m && step[i+a[j]]==INT_MAX)//第一次涉足这个台阶
{
step[i+a[j]] = step[i] + 1;
}
else if(i + a[j] <= m)//不是第一次涉足,比较取最小值,动态规划核心算法
{
step[i+a[j]] = step[i] + 1 < step[i+a[j]] ?
step[i] + 1 : step[i+a[j]];
}
}
}
return step[m]==INT_MAX?-1:step[m];
}
int main()
{
int N,M;
cin>>N>>M;
cout<<getMinStep(N,M)<<endl;;
return 0;
} steps[i+j] = min(steps[i]+1,steps[i+j]) //i为石板编号,j为i的约束 steps[N] = 0解法代码如下:
#include <iostream>
#include <vector>
#include <climits>
#include <cmath>
#include <algorithm>
using namespace std;
int main(){
int N,M;
while(cin>>N>>M){
vector<int> steps(M+1,INT_MAX);
steps[N] = 0;
for(int i=N;i<=M;i++){
if(steps[i] == INT_MAX){
continue;
}
for(int j=2;(j*j)<=i;j++){
if(i%j == 0){
if(i+j <= M){
steps[i+j] = min(steps[i]+1,steps[i+j]);
}
if(i+(i/j) <= M){
steps[i+(i/j)] = min(steps[i]+1,steps[i+(i/j)]);
}
}
}
}
if(steps[M] == INT_MAX){
steps[M] = -1;
}
cout<<steps[M]<<endl;
}
return 0;
} //广度优先遍历
import java.util.*; public class Main{ public static void main(String[] args){ Scanner input=new Scanner(System.in); while(input.hasNext()){ int N=input.nextInt(); int M=input.nextInt(); HashMap<Integer, Integer> list=new HashMap<>(); LinkedList<Integer> queue=new LinkedList<>(); list.put(N, 0); //当前所在位置,0步 queue.add(N); while(!queue.isEmpty()){ int num=queue.remove(); if(num==M){ //满足条件时,输出 System.out.println(list.get(num)); return ; } if(num>M) //石板超过目标时不考虑 continue; HashSet<Integer> arr=new HashSet<>(); //存储当前石板的所有约数 yueShu(num, arr); //找约数 for(int elem: arr){ if(!list.containsKey(num+elem)){ //记录下一次起跳时的石板 list.put(num+elem, list.get(num)+1); queue.add(num+elem); } } } System.out.println(-1); } } public static void yueShu(int num, HashSet<Integer> arr){ //约数计算 for(int i=2; i<=Math.sqrt(num); i++){ if(num%i==0){ arr.add(i); arr.add(num/i); } } } }
#include<stdio.h>
#include<math.h>
#ifdef debug
#define tracking 85678
#define N 8
#define M 85678
#endif
int yue(int x, int* res){
int i=2;
int nums=0;
for(i=2;i<=sqrt((double)x);i++){
if(x%i==0){
res[nums++]=i;
res[nums++]=x/i;
}
}
return nums;
}
int main(){
int i,j;
#ifndef debug
int N,M;
#else
int trackfrom;
#endif
int steps[100001];
#ifndef debug
scanf("%d%d",&N,&M);
#endif
for(i=N;i<=M;i++)steps[i]=100001;
steps[N]=0;
for(i=N;i<=M-1;i++){
if(steps[i]!=100001){
int q,yues[500]={0};
int cc = yue(i,yues);
int mul=0;
#ifdef debug
printf("i=%d,",i);
for(q=0;q<cc;q++)printf(" %d",yues[q]);
printf("\n");
#endif
for(mul=0;mul<cc;mul++){
if(i+yues[mul]<=100000)
{
if(steps[i]+1<steps[i+yues[mul]]){
steps[i+yues[mul]]=steps[i]+1;
#ifdef debug
printf("step [%d] is set to %d, from [%d]\n",i+yues[mul],steps[i]+1,i);
if(i+yues[mul]==tracking)trackfrom=i;
#endif
}
}
}
}
}
#ifdef debug
if(steps[tracking]!=100001)printf("tracking %d,result=%d,trackfrom %d\n",tracking,steps[tracking], trackfrom);
#else
if(steps[M]!=100001)printf("%d\n",steps[M]);
#endif
else printf("-1\n");
return 0;
}
考虑N,M的取值范围,dfs首先不考虑,因为有明显的记忆过程,所以考虑使用动态规划。 构造dp矩阵,dp[M+1],dp[M]表示,从N——>M的最少步骤,显然可以得到条件,dp[N]=0, 设其他值为INT_MAX。 对于dp[N] 遍历N的因子(sub[i-j]) dp[N+sub[i-j]]即为可到达 且从N一步到达,这里dp[N+sub[i-j]]和dp[N]+1取最小值即可。
//小易居然又开始跳石板了...他肯定是疯了
#include<bits/stdc++.h>
using namespace std;
//保存因子,这里不能暴力求因子,会超时,要i×i<=n,同时保存除数和被除数。
void getsub(vector<int>&,int);
int main()
{
int N,M;
cin>>N>>M;
vector<int>sub;
vector<int>dp(M+1,INT_MAX);
dp[N]=0;
//构造dp矩阵
for(int i=N;i<=M;++i){
if(dp[i]==INT_MAX)
continue;
getsub(sub,i);
for(int j=0;j<sub.size();++j){
if(i+sub[j]<=M)
dp[i+sub[j]]=min(dp[i+sub[j]],dp[i]+1);
}
}
if(dp[M]==INT_MAX)
cout<<-1<<endl;
else
cout<<dp[M];
return 0;
}
void getsub(vector<int>&sub,int num)
{
sub.clear();
for(int i=2;i*i<=num;++i){
if(num%i==0){
sub.push_back(i);
if(i!=num/i)
sub.push_back(num/i);
}
}
} #include <iostream>
#include <climits>
#include <vector>
using namespace std;
int main()
{ int N,M; while(cin>>N>>M) { vector<int> steps(M+1, INT_MAX); steps[N] = 0; for(int i=N;i<=M;i++) { if(steps[i] != INT_MAX) for(int j=2;j*j<=i;j++) { if(i%j == 0) { if(i+j <= M) steps[i+j] = min(steps[i]+1, steps[i+j]); if(i+i/j <= M) steps[i+i/j] = min(steps[i]+1, steps[i+i/j]); } } } if(steps[M] == INT_MAX) steps[M] = -1; cout<<steps[M]<<endl; } return 0;
}
import java.util.*;
/**
* 题目描述
* 小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......
* 这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,
* 小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。
* 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
*
* 例如:
* N = 4,M = 24:
* 4->6->8->12->18->24
* 于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板
* 输入描述:
* 输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)
* 输出描述:输出小易最少需要跳跃的步数,如果不能到达输出-1
* 示例
* 输入4 24
* 输出5
*
*
* 掉的坑:
* 1.使用(m == n) ( [-128, 127] 时相等 )
*/
public class 挑石板 {
public static void main(String[] args) {
//输入
Scanner sc = new Scanner(System.in);
Integer n = sc.nextInt();
Integer m = sc.nextInt();
Integer result = -1;
//处理
if (m.equals(n)) {
System.out.println(0);
} else {
int step[] = new int[m + 1];
step[n] = 0;
for (int i = n; i < m; i++) {
Set<Integer> factor = getFactor(i);
for (Integer j : factor) {
if (i % j == 0 && j <= m - i) {
if (step[j + i] > step[i] + 1 || step[i + j] == 0 && (step[i] != 0 || i == n)) {
step[j + i] = step[i] + 1;
}
}
}
}
//输出
if (step[m] == 0)
System.out.println(-1);
else
System.out.println(step[m]);
}
}
private static Set<Integer> getFactor(Integer n) {
Set<Integer> res = new HashSet<>();
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
res.add(i);res.add(n/i);
}
}
return res;
}
}
#include <iostream>
#include <vector>
using namespace std;
void GetFewNum(int num, vector<int> &a)
{
int tem = sqrt(num);
for (int i = 2; i <= tem; i++)
{
int temp = num / i;
if (temp == num / i)
{
if (temp != i)
{
a.push_back(temp);
a.push_back(i);
}
else
a.push_back(i);
}
}
}
int main()
{
int n, m;
cin >> n >> m;
vector<int> res(m+1,0);
int k = n;
res[k] = 1;
while (k<=m)
{
if (res[k] == 0)
{
k++;
continue;
}
vector<int> a;
GetFewNum(k,a);
for (int i = 0; i < a.size(); i++)
{
if (a[i] + k <= m && res[a[i] + k] == 0)
{
res[a[i] + k] = res[k] + 1;
}
else if (a[i] + k <= m && res[a[i] + k] != 0)
{
res[a[i] + k] = res[a[i] + k] < res[k] + 1 ? res[a[i] + k] : res[k] + 1;
}
}
k++;
}
if (res[m] != 0)
cout << res[m] - 1 << endl;
else
cout << -1 << endl;
return 0;
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in
);
int a = sc.nextInt();
int b = sc.nextInt();
if(a==b){
System.out.println(0);
}else {
int []c = new int [b+1];
for(int i = a ; i < b ; i++ ){
for(int j = 2 ; j <= Math.sqrt(i) ; j++ ){
if(i/j*j==i){
if((i==a||c[i]!=0)&&i+i/j<=b){
if(c[i+i/j]==0||c[i+i/j]>c[i]+1){
c[i+i/j]=c[i]+1;
}
}
if((i==a||c[i]!=0)&&i+j<=b){
if(c[i+j]==0||c[i+j]>c[i]+1){
c[i+j]=c[i]+1;
}
}
}
}
}
System.out.print(c[b]==0?-1:c[b]);
}
}
}
#include<stdio.h>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
int book[200005];
struct node{
int val,step;
node(int val,int step):val(val),step(step){}
};
int main(){
int N,M,i;
//freopen("input.txt","r",stdin);
while(scanf("%d%d",&N,&M)!=EOF){
memset(book,0,sizeof(book));
queue<node> Q;
Q.push(node(N,0));
book[N]=1;
int flag=-1;
while(!Q.empty()){
node head=Q.front();Q.pop();
if(head.val==M){
flag=head.step;
break;
}
if(head.val>M) continue;
int n=(int)sqrt(head.val);
for(i=2;i<=n;i++)
if(head.val%i==0){
int other=head.val/i;
if(book[head.val+i]==0){
Q.push(node(head.val+i,head.step+1));
book[head.val+i]=1;
}
if(other!=i&&book[head.val+other]==0){
Q.push(node(head.val+other,head.step+1));
book[head.val+other]=1;
}
}
}
printf("%d\n",flag);
}
}//直接bfs就可以啦~ package 跳石板; import java.util.ArrayDeque; import java.util.Deque; import java.util.Scanner; /** * @author ayonel * @create 2017-08-28 22:09 * @blog https://ayonel.me * 广搜 **/ public class Main { public static boolean[] notPrime; public static boolean[] visited; public static void genPrime(int n){ notPrime = new boolean[n+1]; for (int i = 2; i < n; i++) { if (!notPrime[i]) { for (int j = 2; i*j < n; j++) { notPrime[i*j] = true; } } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int M = sc.nextInt(); if (M==N){ System.out.println("0"); return; } visited = new boolean[M+1]; visited[0] = true; visited[1] = true; genPrime(M); Deque<Integer> deque = new ArrayDeque<>(); Deque<Integer> deep = new ArrayDeque<>(); deque.push(N); deep.push(0); int node,dep, fac1, fac2; while (!deque.isEmpty()){ node = deque.poll(); dep = deep.poll(); if (!notPrime[node]){ //质数 continue; } for (int j = 2; j <= (int)Math.sqrt(node); j++) { if (node % j == 0){ fac1 = node+j; fac2 = node+node/j; if (fac1 == M||fac2 == M){ System.out.println(dep+1); return; } if (fac1<=M && notPrime[node+j] && !visited[node+j]){ deque.offer(fac1); deep.offer(dep+1); visited[fac1] = true; } if (fac1 != fac2 && fac2 <= M && notPrime[fac2] && !visited[fac2]){ deque.offer(fac2); deep.offer(dep+1); visited[fac2] = true; } } } } System.out.println(-1); } }
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<queue>
#include<fstream>
#include<stdlib.h>
#include<ctime>
#include<vector>
using namespace std;
#define FOR(i,LE,RI) for(i=LE;i<RI;++i)
#define MEM(x,i) memset(x,i,sizeof(x))
#define COUT(DATA,ED) printf("%d%c",DATA,ED)
#define CIN(val) scanf("%d",&val)
#define LL long long
const int LE=2000000;
const int INF=2000000;
int dp[120000];
int dest[LE],nxt[LE];
int first[210000],zz;
int n;
void one_set(int val){
for(int alt=first[val];alt!=-1;alt=nxt[alt]){
int sum=dest[alt]+val;
if(sum>n) continue;
dp[sum]=min(dp[sum],dp[val]+1);
}
}
void init(){
int i,j;
int start,result;
CIN(start);
CIN(n);
MEM(first,-1);
zz=0;
FOR(i,2,n+1){
dp[i]=INF;
FOR(j,2,n+1){
if(i*j>n) break;
dest[zz]=i;
nxt[zz]=first[i*j];
first[i*j]=zz++;
}
}
dp[start]=0;
FOR(i,start,n+1){
one_set(i);
}
if(dp[n]>n) dp[n]=-1;
COUT(dp[n],'\n');
}
int main(){
init();
return 0;
} #include <iostream>
#include <vector>
using namespace std;
inline void divisor(const int& n,vector<int>& vec)
{
for(int i=2;i<n;i++)
{
if(n%i == 0) vec.push_back(i);
}
}
inline void ConstructTree(const vector<int>& vec,int depth,int& m)
{
if(m>100000) return;
vector<int> next_depth;
for(int i=0;i<vec.size();i++)
{
vector<int> divisors;
divisor(vec[i],divisors);
for(int j =0;j<divisors.size();j++)
{
divisors[j]+=vec[i];
if(divisors[j]==m) {cout<<depth+1<<endl;return;}
if(divisors[j]<m) next_depth.push_back(divisors[j]);
}
}
ConstructTree(next_depth,depth+1,m);
}
int main()
{
int n,m;
cin>>n>>m;
int depth=0;
vector<int> init_vec;
init_vec.push_back(n);
ConstructTree(init_vec,depth,m);
//cout<<setp<<endl;
return 0;
}
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main{
public static void main(String[] args) { // TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int M = scanner.nextInt();
System.out.println(jumpStone_dp(N,M)); }
private static int jumpStone_dp(int n, int m) { //动态规划求步数,O((m-2)*m^1/2)=O(n^(3/2))
// TODO Auto-generated method stub
int dp[] =new int[m+1];
for(int i=2;i<m+1;i++)
dp[i] = (i==n)? 0:Integer.MAX_VALUE; //使用MAX_VALUE表示不可达
for(int j=n;j<=m-2;j++){ //这里j自增到m-2而不是m
if(dp[j]==Integer.MAX_VALUE) continue;
List divisors = getDivisor_dp(j);
if(null == divisors) continue;
for(int i=0;i<divisors.size();i++){
if(divisors.get(i)+j>m) continue;
/*关键代码,dp[i]表示当值为i时,从n增加到i的最小步数,首先遍历从n到m的所有数,并在每次遍历中找到当前数i的所有约数,这样就知道了i的下一步可以到达哪些数字,然后Math取最小值*/
dp[divisors.get(i)+j] = Math.min(dp[divisors.get(i)+j], dp[j]+1);
}
}
if(dp[m]==Integer.MAX_VALUE) return -1;
return dp[m];
}
private static List getDivisor_dp(int n) { //求约数集合,算法复杂度n^1/2
// TODO Auto-generated method stub
if(n<3) return null;
List list = new ArrayList();
for(int i=2;i<=Math.sqrt(n);i++){
if(n%i == 0) {
list.add(i);
if(n/i!=i) list.add(n/i);
}
}
return list;
}
}