整数变换问题-----回溯法

整数变换问题:关于整数i 的变换f 和g 定义如下:f(i)=3i;g(i)=i/2。 试设计一个算法,对于给定的2 个整数n 和m,用最少的f 和g 变换次数将n 变换为m。 例如,可以将整数15 用4 次变换将它变换为整数4:4=gfgg(15)。当整数n 不可能变换为整数m 时,算法应如何处理?

这是3n+1问题的变形。为了找最短变换序列,用逐步加深的回溯法搜索。子集树算法。

开发环境是vs2013,c++语言

算法步骤:
1、从键盘获取要变换的数n,要变换成的数m
2、将变换的次数k先设置为1,使用search(1,n)进行回溯搜索,如果搜索到了,则输出结果;否则,将k递增一次,继续执行search直到找到或者超过最大变换次数。
3、search(dep,n)递归回溯搜索,每次都进行3*n和n/2,并从这两分支不断延续两个分支下去,直到找到或者超出界限为止。
4、算法时间复杂度:显然是O(n)

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include"iostream"
using namespace std;

static int n;//要变换的数
static int m;//要变换成的数
static int k;//变换的次数
static bool found;//查找结果
static int result[100];//最多变换100次

bool search(int dep, int n);
void compute();
int fg(int n, int i);

void compute(){
    k = 1;
    found = false;
    while (!search(1, n)){
        k++;
        if (k > 100)
            break;
        if (found)
            break;
    }
}

bool search(int dep, int n){
//search实现回溯搜索
    if (dep>k){
        return false;
    }
    for (int i = 0; i<2; i++){
        int num = n;
        num = fg(num, i);
        result[dep] = i;
        if (num == m || search(dep + 1, num)){
            found = true;
            return true;
        }
    }
    return false;
}

int fg(int n, int i){
    if (i == 0)
        return n / 2;
    else
        return 3 * n;
}

void main(){
    cout << "输入要变换的数: ";
    cin >> n ;
    cout << "输入要变换成的数: ";
    cin >> m ;
    for (int i = 0; i<99; i++){
        result[i] = 0;
    }
    compute();
    if (found){
        cout << "运算次数:" << k << "次" << endl;
        cout << "运算过程:";
        for (int i = k; i >= 1; i--){
            if (result[i] == 0)
                cout << "g";
            else if (result[i] == 1)
                cout << "f";
        }
        cout << endl;   
    }
    else{
        cout <<n<<"无法变换成"<<m <<endl;
    }
    system("pause");
}
    原文作者:回溯法
    原文地址: https://blog.csdn.net/u014377853/article/details/49998281
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞