一. 实验目的及实验环境
实验目的:了解回溯法并且熟练运用。
环境:devc++。
二. 实验内容
1. 删数问题
给定 n 位正整数 a,去掉其中任意 k 个数字后,剩下的数字
按原次序排列成一个新的正整数 n (1<=n<=200)位的正整数 a 和
k,k 小于 n。
2.整数变换
给定整数 i 的 f 变换和 g 变换分别为 f(i)=3*i;g(i)=└ i/2
┘;└ ┘表示向下取整。现在给定 n,m,即通过 f 和 g 变换把
n 变为 m,求所需变换最小的次数。
三.方案设计
1. 这个问题是最优子结构问题,即局部最优能决定全局最优解,
可以使用贪心算法进行解决。n 个正整数去掉 s 个数字,求使得到
的新的正整数最大的删除方案可以等价为:对于 n 个正整数组成的
数字,一个一个地依次去掉 s 个数字,要求每删除一个数时,都使
删除后的新的正整数最小。因此问题转化为求解删除一个数字时是
新的数字最小的方案,求得这个方案后只需要对其执行 s 次即可。
2. 将变换的次数 step 先设置为 1,使用 dfs(1,n)进行迭代加
深搜索,如果搜索到了,则输出结果;否则,将 step 递增一次,
继续执行 def 直到找到或者超过最大变换次数。
dfs(dep,n)迭代加深搜索,每次都进行 3*n 和 n/2,并从这两分
支不断延续两个分支下去,直到找到或者超出界限为止。
五.总结
1. 实验过程中遇到的问题及解决办法及对调试过程的心得体会。
开始时思路不是很清晰,但后来通过 csdn 得到了启发思路,最终
解决了这些问题,以后还是要加大对算法题的练习,不然就会生
疏。
六.附录:源代码(电子版)
1.
#include
#include
char num[100];
int main(void){
int n,i;
printf("请输入正整数 n: ");
scanf("%s",num);
printf("输入要删除的位数:");
scanf("%d",&n);
if(n>=strlen(num)){
printf("%d",0);
return 0;
}
while(n--){
i=0; //每次开始将 i 初始化为 0,表示重新开始检测下
降点
while(ifor(int j=i;j
#include
using namespace std;
const int MAX = 25;
int n, m;
int bestx[MAX+1];//变换序列
int step=1;
//搜索深度,逐步加深
bool found = false;
//两种变换
int change(int status, int n){ //0 为 g 1 为 f
return status?n*3:n/2;
}
//迭代加深搜索
bool dfs(int dep, int n){
if(dep > step){ //超过限制深度
return false;
}
for(int i=0; i<2; i++){
int temp = change(i, n);
bestx[dep] = i; //记录当前变换状态
if(temp == m || dfs(dep+1, temp)){//已找到
found = true;
return true;
}
}
return false;
}
int main(void){
cout << "请输入正整数 n 和 m:";
cin >>n>>m;
while(true){
if(dfs(1, n) || ++step > MAX){ //找到 || 超过限
制深度
if(found){
cout << n << "变为" << m << "最少的变换次数
为:" << step << endl;
cout << "变换过程为:";
for(int i=step; i>=1; i--){
bestx[i]?cout<<'f':cout<<'g';
cout << " 超 过 默 认 变 换 步 数 ("<