/*
构造高精度数据:
构造一个尽可能大的数,使其从高到底前一位能被一整除,前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;
}
算法设计与分析:第五章 回溯法 5.7构造高精度数据
原文作者:回溯法
原文地址: https://blog.csdn.net/qingyuanluofeng/article/details/47189449
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/qingyuanluofeng/article/details/47189449
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。