蓝桥杯 角谷猜想 深搜


你听说过角谷猜想吗?
任意的正整数,比如 5, 我们从它开始,如下规则计算:
如果是偶数,则除以2,如果是奇数,则乘以3再加1.
如此循环,最终必会得到“1” !


比如 5 的处理过程是:
5
16
8
4
2
1


一个正整数经过多少步才能变成1, 称为角谷步数。
对于5而言,步数也是5
对于1,步数为0


本题的要求是,从标准输入给定一个整数n(1<n<300)表示角谷步数
求满足这个角谷步数的最小的正整数


例如:


输入:
3
则输出:
8


输入:
4
则输出:
16


输入:
7
则输出:

3


大体来说,有两种暴力方案偷笑,1.从1开始枚举到n,直到找到一个满足这种算法的数字,因为从小到大枚举,所以可以保证找到的数字最小。2.通过DFS搜索,也是我的方法,下面说一下这种思路:


如果我们倒过来看,即从1开始看,然后逆向推,有两个方向,1.上一个数是奇数,2.上一个数是偶数。也就是说,如果我们从1开始不停地向上找,实际上找到的所有的数字可以构成一棵二叉树,但其中不免会有很多无效的分支:

1.我们来看奇数的处理方法,num*3+1=x,而num的值如果是奇数最小也是3,也就是说3的下一个数字都达到10,所以对于小于10的数字num的前一个数不可能是奇数;

2.如果要计算num的上一个数为奇数的情况,需要计算(num-1)/3的值,如果num-1本身就不能被3整除,那也说明这个数的上一个数不可能为奇数

3.如果条件2满足,但是算出的上一个数却是偶数,这种情况也要去除掉,比如,我们本来想计算13的上一个奇数,但(13-1)/3=4,4为偶数,所以这就是一种不符合条件的数值


严格的来说,这题是需要用大数来解的,因为第一条分支的数是呈指数级增长的(每次都乘2),当n达到200甚至300的时候,一般的数据类型肯定是没法用,不过只要前面的思路有了,解法是不变的。


#include<iostream>
using namespace std;
int Min=42949672;
void dfs(int step,int num,int count)
{
	if(count==step)
	{
		
		if(num<Min)
		Min=num;
		return;
	}
	dfs(step,2*num,count+1);
	if(num>=10&&(num-1)%3==0&&((num-1)/3)%2==1)
	dfs(step,(num-1)/3,count+1);
}


int main()
{
	int step;
	cin>>step;
	dfs(step,1,0);
	cout<<Min;
	return 0;
}



你可能感兴趣的:(ACM,蓝桥杯,深搜,角谷猜想)