整数变换问题
SDUTOJ 整数变换问题
Problem Description
整数变换问题。关于整数i的变换f和g定义如下:f(i)=3i;
试设计一个算法,对于给定的2 个整数n和m,用最少的f和g变换次数将n变换为m。例如,可以将整数15用4 次变换将它变换为整数4:4=gfgg(15)。当整数n不可能变换为整数m时,算法应如何处理?
对任意给定的整数n和m,计算将整数n变换为整数m所需要的最少变换次数。
Input
输入数据的第一行有2 个正整数n和m。n≤100000,m≤1000000000。
Output
将计算出的最少变换次数以及相应的变换序列输出。第一行是最少变换次数。第2 行是相应的变换序列。
Sample Input
15 4
Sample Output
4
gfgg
Hint
Source
该问题乍一看没有什么头绪,最少变换次数怎么找???
是不是比m大就得进行除操作,比m小就得进行乘操作??
在不确定是不是最优解的情况下怎么把操作符加入队列???
问题解决思路:
用DFS进行探索,但是每次只探索一层,两种操作都进行
找到的第一个匹配的结果即为所求的解。
找到最优解后,进行回溯,在回溯的过程中把之前走过的路径加入队列
即可得到最优解的路径。
搜索树和代码如下:
#include<bits/stdc++.h>
using namespace std;
#define N 25
#define inf 0x3f3f3f3f
int n, m;
//定义k来表示搜索树的深度
int k = 1;
//定义一个队列来存放各类操作
queue<char> q;
bool DFS(int x, int n)
{
//防止死循环,保证最多只能访问到下一层
if(x > k)
return false;
//找到返回true
if(n == m)
return true;
//这里必须用一个temp做临时变量
//若不用temp做临时变量,回溯的时候n的值发生变化
//导致结果异常
int temp = n;
//左右都做一遍,看看能否到达目的
for(int i = 0; i < 2; i++)
{
if(i == 0)
temp = n * 3;
else
temp = n / 2;
if(DFS(x+1, temp))
{
if(i == 0)
q.push('f');
else
q.push('g');
//这里必须要return true
//因为只需要找到第一个满足条件的那条路径
//回溯返回的时候把路径上的运算加入队列即可。
return true;
}
}
//如果没找到返回false,k++
//可往更深一层探索
return false;
}
int main()
{
cin >> n >> m;
//找不到,往更深一层探索!
while(!DFS(0, n))
k++;
cout << k << endl;
while(!q.empty())
{
cout << q.front();
q.pop();
}
return 0;
}