分支限界法基本思想:
分支限界法以广度优先或以最小消耗优先的方式搜索解空间树。
基本策略为:
1.先分支:在扩展结点处,生成其所有的子结点。
2.再限界:根据题目要求设置限界函数,根据函数值,选择所有子结点中最有利的结点作为下一个扩展结点。
经过两步使搜索朝着解空间树上最优的分支推进,以便尽快找出最优解。
问题描述:
输入m,n。假设当前有三种操作:加1,乘2,平方;问从m变换至n最少需要几次运算;
问题分析:
1.根据分支限界法步骤,先分支:每个当前结点将有三个子结点;
2.再限界:若分支后的子结点已经出现,本题中若出现则代表走过则剪枝;若当前的子结点数值超过目标,剪枝;
3.所需数据结构:需要一个队列时刻访问当前结点;需要一个一维数组,记录从起始结点至当前结点的步数,若为-1则表示未经过;
备注:小学生最近开始学英语,大神不要吐槽,指点一二也是好,(^__^) 嘻嘻……
代码展示:
#include <iostream>
#include <queue>
using namespace std;
// note the steps from began to i
int step[10001];
// for visit current node
queue<int> q1;
//there is a function which is from m to n
int FmTn(int n);
//there is a function which is the rule of number change
int moveto(int u, int num);
int main()
{
//readData
int m, n;
cin >> m >> n;
//initData
// -1 means not path from m to i
for (int i(m); i <= n; ++i)
step[i] = -1;
q1.push(m);
step[m] = 0;
//run
cout << FmTn(n) << endl;
return 0;
}
int FmTn(int n)
{
int u, v;
while(!q1.empty())
{
// get current node
u = q1.front();
q1.pop();
for (int i(0); i < 3; ++i)
{
*//first : expand*
//the node after three change ways
v = moveto(u, i);
*//last : impose*
//find
if (v == n)
return (step[u] + 1);
//have not found the answer, stroy this path and select next answer
if (v < n && step[v] == -1)
{
q1.push(v);
step[v] = step[u] + 1;
}
}
}
}
int moveto(int u, int num)
{
switch(num)
{
case 0: u += 1;break;
case 1: u *= 2;break;
case 2: u *= u;break;
default:break;
}
return u;
}