整數變換問題-----回溯法

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章