算法设计与分析:第五章 回溯法 5.7构造高精度数据

/*
构造高精度数据:
构造一个尽可能大的数,使其从高到底前一位能被一整除,前2位能被2整除,...,前n位能被n整除
分析:
解空间:记高精度数据为a1a2...an,
则(a1*10^(n-1) + a2*10^(n-2) + ... + an)整除n

如何搜索?
从高位到低维逐位尝试,失败回溯的算法。算法的首位从1开始枚举,以后各位从0开始枚举。生成的高精度数据用数组从高位到低位
存储,一号元素存储最高位。

如何确定和保留最优解?
用数组A作为当前求解的高精度数据的暂存处。数组B为当前最大的满足条件的数。求解出的满足条件的睡之间只需要比较位数就能确定大小。
n为当前满足条件的最大数据的位数,当i > n时,位数多数据一定大;i = n时,由于搜索是由小到大金星的,位数相等时后来满足条件的
数据一定比前面的大。

输出:
447204888644483284
*/

/*
关键:
1 设置数组首位为1 A[1] = 1;
2 循环退出条件为A[1] > 9 ,while(A[1] <= 9)//因为最后会回溯到A[1],而A[1]的值最多为9
3 当 i >= n时,更新数据
		if(i >= n)//寻找到更大的数据,将临时数组中的数据保存到最终数据中
		{
			n = i ;//更新n

4 检查第i位是否符合条件
		r = r % i;//获取第i位的余数
		if(r != 0)//第i位失败
5 构造第i位可能的解
			//构造第i位的可能解,也就是加上i-r,构成i缺少的部分
			A[i] = A[i] + i - r;

6 确定第i位是否需要回溯,是当其值大于9,并且位数大于1
while(A[i] > 9 && i > 1)//搜索到第i位的解,回溯到前一位
7 回溯的做法是:另当前位为0,A[i] = 0 , 再减小位数;i--,另上一位可能解为:A[i] = A[i] + i;
				A[i] = 0;//置当前位为0
				i = i - 1;
				A[i] = A[i] + i;//?尝试前一位,加i的原因是,在前一位的基础上加i,上一位必定能被i整除。
*/

#include <iostream>
#include <string.h>

using namespace std;

void num()
{
	//设置数组,用于暂存
	int A[101] , B[101];
	//初始化数组
	memset(A, 0 , sizeof(A));
	memset(B, -1 , sizeof(B));
	//设置暂存数组的首位为1
	A[1] = 1;
	int i = 1;
	int n = 1;
	while(A[1] <= 9)//因为最后会回溯到A[1],而A[1]的值最多为9
	{
		if(i >= n)//寻找到更大的数据,将临时数组中的数据保存到最终数据中
		{
			n = i ;//更新n
			for(int k = 1 ; k <= n ; k++)
			{
				B[k] = A[k];
			}
		}
		i = i + 1;
		int r = 0;
		for(int j = 1 ; j <= i ; j++)//检查第i位是否符合条件
		{
			r = r * 10 + A[j];
		}
		r = r % i;//获取第i位的余数
		if(r != 0)//第i位失败
		{
			//构造第i位的可能解,也就是加上i-r,构成i缺少的部分
			A[i] = A[i] + i - r;
			while(A[i] > 9 && i > 1)//搜索到第i位的解,回溯到前一位
			{
				A[i] = 0;//置当前位为0
				i = i - 1;
				A[i] = A[i] + i;//?尝试前一位,加i的原因是,在前一位的基础上加i,上一位必定能被i整除。
			}
		}
	}
	for(int i = 1 ; i < 101 ; i++)
	{
		if(B[i] == -1)
		{
			break;
		}
		cout << B[i] ;
	}
	cout << endl;
}


void process()
{
	num();
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值