noj加1乘2平方
广度优先搜索典例
00 题目
描述:
最简单的队列的使用
1 #include <iostream> 2 #include <queue> 3 using namespace std; 4 queue<int> q1; 5 int main() 6 { 7 int temp, x; 8 q1.push(5);//入队 9 q1.push(8);//入队 10 temp = q1.front();//访问队首元素 11 q1.pop();//出队 12 q1.empty();//判队列是否为空 13 q1.back();//返回队尾元素 14 q1.size();//返回队列长度 15 }
给定两个正整数m、n,问只能做加1、乘2和平方这三种变化,从m变化到n最少需要几次
输入:
输入两个10000以内的正整数m和n,且m小于n
输出:
输出从m变化到n的最少次数
输入样例:
1 16
输出样例:
3
01 思路0
01-1 类型
虽然看上去感觉有一些无处下手,但是实际上就是一个三叉树,并且要去去找 到达目标节点 的最低高度。
这个图转自
很明显,这是个广搜典型题。
01-2 算法
-
以初始数字(如1)当作根结点,入队,出队,产生三个子节点next,对子节点筛选符合条件的继续进队
关于三个子结点的产生,可以设置标志位标记为0,1,2
-
0->当前值+1
-
1->当前值*2
-
2->当前值*当前值
对应我的change函数
-
-
对next值进行判断
-
当next为终点数字时,就停止,返回高度(高度需要变量来记)
-
当next>终点数字时,不再入队。
-
当next<终点数字时,入队,方便下一步找它的子节点。
-
-
在bfs主控函数中把队列走完,就能解决问题。
-
输出
02 代码0
1 //方法2 2 //按照题目要求使用队列,相应算法是广搜 3 #include<iostream> 4 #include<queue> 5 using namespace std; 6 7 queue<int> q; 8 int m,n; 9 int step[10000]; 10 int used[10000]; 11 12 int bfs();//广度优先搜索 13 int change(int now, int i);//三种变换 14 bool istarget(int now, int next); 15 //判断是否达到目标数字 16 int main(){ 17 cin >> m >> n; 18 //始末位置 19 q.push(m); 20 //m入队 21 cout << bfs() << endl; 22 return 0; 23 } 24 int bfs(){ 25 int next; 26 while(!q.empty() ){ 27 int now = q.front(); 28 q.pop(); 29 used[now]=1; 30 for(int i=0; i<3; i++){ 31 next = change(now,i); 32 //生成当前节点的下一节点(一共三个) 33 if(istarget(now, next)){ 34 return step[next]; 35 }//如果就达到目标,就返回走了几步,由于使用广搜,就是最短路径 36 } 37 } 38 return 0;//这点很重要,虽然code永远到不了这里 39 } 40 41 bool istarget(int now,int next){ 42 if(next<=n && used[next]==0){//确保子节点未超过目标值且未被访问过 43 used[next]=1; 44 step[next] = step[now] + 1;//从当前到子节点需+1 45 //核心判断 46 if(next == n){ 47 return true; 48 } 49 else{ 50 q.push(next); 51 //如果不是就吧这个节点当成普通节点放入队列 52 } 53 } 54 return false; 55 } 56 57 int change(int now, int i){ 58 if(i==0) return now+1; 59 if(i==1) return now*2; 60 else return now*now; 61 }
03 思路1
03-1 类型
动态规划,更为简洁,只需要一个main函数和两个指针
03-2 算法
-
从起始数字开始,我设置一个行走位逐个去走到终点
-
对i进行讨论
-
先设置基准步伐,比较i的路经长度和i-1的路径长度+1
-
当i为偶数,比较到达i的路径长度和i/2的路径长度+1
-
当i为平方数,(可以提前设置一个int 的i的根号,当t*t==i即为这个条件)比较到达i的路径长度和t的路径长度+1
-
-
算法原理,因为i是从m开始走的,所以天然不需要循环,只需不断地调用之前的结果进行比较就能得到新的结果,这就是动态规划的魅力所在。算法时间复杂度为O(m-n).
04 代码1
1 //加1乘2平方 2 3 #include<stdio.h> 4 #include<string.h> 5 #include<iostream> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 const int maxn = 10000+50; 10 int dp[maxn],m,n; 11 12 //min函数内置了 13 int main(){ 14 cin>>m>>n; 15 memset(dp,0x3f3f3f,sizeof(dp)); 16 dp[m] = 0; 17 for(int i = m+1; i <= n; i++){ 18 int t = sqrt(i); 19 dp[i]=min(dp[i],dp[i-1]+1); 20 if(i%2==0){ 21 dp[i] = min(dp[i], dp[i/2]+1); 22 } 23 if(t*t == i){ 24 dp[i] = min(dp[i],dp[t]+1); 25 } 26 } 27 cout << dp[n] << endl; 28 return 0; 29 }