任意的正整数,比如 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
这个题刚开始看的时候想用递归求,来倒推,来显示一下我还算是理解递归的,结果败北了。对于小数据(比如两位数)还行,对于稍大这么一点点的就严重超时,最后黔驴技穷了,还是暴力吧。
在这贴一下我的错误的递归算法,要是有哪位大神会的话还望指点一下
#include <iostream>
using namespace std;
int step,mins=99999999;
void DFS(int n,int count)
{
if(count==step)
{
if(n<mins)
mins=n;
return;
}
DFS(n*2,count+1);
if((n-1)%3==0&&((n-1)/3)%2==1&&n>=10)
DFS((n-1)/3,count+1);
}
int main()
{
while(cin>>step)
{
DFS(1,0);
cout<<mins<<endl;
}
return 0;
}
暴力中对算法又有了优化,优化算法类似于记忆话搜索和哈希算法。
比如说当前数是temp,如果它最后算到1的步数已经有了,那我们就不用再算了,直接加上这个步数就行了。
数据类型用long long
#include <iostream>
#include <memory.h>
using namespace std;
int main ()
{
long long a[10005];
memset(a,0,sizeof(a));
int n;
cin>>n;
for(long long i=2;; i++)
{
long long temp=i,count=0;
while(temp!=1)
{
if(temp<=10000&&a[temp]!=0)
{
count+=a[temp];
break;
}
if(temp%2==0) temp=temp/2;
else temp=temp*3+1;
count++;
}
if(i<=10000)
a[i]=count;
if(count==n)
{
cout<<i<<endl;
break;
}
}
return 0;
}