整數變換問題:關於整數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");
}