UVa100 - The 3n + 1 problem

有一个算法为

		1. 		 input n

2. print n

3. if n = 1 then STOP

4. if n is odd then

5. else

6. GOTO 2


生成的序列的长度称为n的cycle-length。

input:i和j(i和j都小于1000,000)

output:i和j之间所有数的cycle-length的最大值

Sample Input

1 10
100 200
201 210
900 1000

Sample Output

1 10 20
100 200 125
201 210 89
900 1000 174

解题思路:

        申请一个堆,用来存储1~999999的cycle-length。对于每一对输入i和j,从小到大遍历,得到cycle-length后将结果存入堆中;计算时如果遇到了先前计算过的数,可以break当前算法的循环,直接在堆中查找剩余长度。

        如果n是2的幂,那么可以直接推出cycle-length,例如n=16时,序列就为16,8,4,2,1;cycle-length = 5.

        【我想也许存在更高效的算法,因为16之前的数要么为奇数5,要么为偶数32;而8之前不可能为奇数,只能是偶数16;造成这个差别的原因是16 - 1 = 15能被3整除,而8 - 1 = 7不能被3整除……而且程序结果证明,1到999999之间最大的cycle也只有五百多,所以猜测这个序列是很有规律的……】

代码:

#include 
using namespace std;

int arr[1000000];
int main()
{
	int l = 1 ;
	int t = 1 ;
	while(l < 1000000)
	{
		arr[l] = t ;
		l *= 2 ;
		t ++ ;
	}

	unsigned int i,j ;
	
	while(cin >> i)
	{
		cin >> j;

		cout << i << ' ' << j << ' ' ;
		if(i > j)
		{
			unsigned int tmp = i ;
			i = j ;
			j = tmp ;
		}

		int maxlength = 0 ;

		for(unsigned int c = i ; c <= j ; c ++)
		{
			unsigned int tmp = c ;
			int count = 0 ;
			
			while(tmp)
			{
				if (tmp < 1000000 && arr[tmp])
				{
					count += arr[tmp] ;
					break ;
				}
				if(tmp % 2)
					tmp = tmp * 3 + 1 ;
				else
					tmp /= 2 ;
				count ++ ;
			}
			arr[c] = count ;
			if (count > maxlength)
			{
				maxlength = count ;
				
			}
		}
		cout << maxlength << endl ;
	}
	return 0 ;
}

我的CT(code teacher)说,这个代码真难看~嗯,还要加油

你可能感兴趣的:(AC)