UVa 3n+1 问题

           《挑战编程》第一个问题3n+1 看似非常简单的问题。但如果只是简单的使用蛮力法,就是超时的结果。所以在计算一个数n,它的节数的同时。需要把它经过的数记录下来。因为这些数的节数都与n有关。在查找n的同时,可以把这些数的节数同时也找出来。 代码如下:

#include <vector>
#include <stdio.h>
#include <iostream>
using namespace std;

const int scale = 5000000;

int answer[scale + 1] = {0};
vector< unsigned int > Numvec;

// 查找num的值及其经过的数的值
void funfind( unsigned int num);
//  处理栈中的经过的数
void process();

/*
 * 递归查找经过的各个数的 节数。 
 * 对于同一个数将不会重复查找
 *
 */
void funfind(unsigned int num)
{
	Numvec.push_back( num );
	if ( !(num % 2) && num / 2 > scale   ) // 为偶数, 且超值了。
	{		
		funfind( num / 2);
	}
	else if( !(num % 2) && num / 2 <= scale &&  answer[ num / 2 ]  )
	{
		Numvec.push_back( num / 2 );
		process();
	}
	else if( !(num % 2) && num / 2 <= scale && answer[ num / 2 ] == 0  )
	{
		funfind( num / 2);
	}
	else
	{
		funfind( 3 * num + 1);
	}

}
/*
 * 处理队列中的各个数,计算其节数。
 *
 */
void process( )
{
	size_t vecsize = Numvec.size();
	int addNumber = answer[ Numvec[ vecsize -1 ] ];

	vector< unsigned int >::iterator end = Numvec.end();

	for(vector<unsigned int >::iterator it = Numvec.begin();
			it != end; ++ it)
	{
		if( (*it) < scale )
			answer[ *it ] = vecsize - 1 + addNumber;
		vecsize --;
	}
	Numvec.clear();
}


int main( int argc, char ** argv)
{
	int low , high;
	int max = 0;
	int pos = 0 ;
	answer[1] = 1;
	answer[2] = 2;

	while( scanf("%d %d",&low, &high ) != EOF  )
	{
		max = 0;

		cout << low << " " << high << " ";
		if( low > high )
		{
			int temp = low;
			low = high;
			high = temp;
		}
		for(int i = low; i <= high; ++i )
		{
			if(!( answer[i] ) )
				funfind(i);
			if ( max < answer[i] )
			{
				max = answer[i];
				pos = i;
			}	
		}
			cout  << max << endl;
	}
	return 0;
}


 

 

       这个题目提醒我们,应该考虑较多的是时间复杂度。毕竟现在的计算机的内存都是非常大的。我们编写的程序如果只是多占用几MB或十几MB,却能大大的降低时间复杂度,这又何乐不为。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值