我一直试图通过使用二叉树来解决这个问题,因为我开始了解它们。 请告诉我这个问题是否可以通过使用二进制树来解决,如果是,那我到目前为止编写的代码有什么问题(在c ++中)? 它给出了错误的答案......
问题: 瓦西亚找到了一个奇怪的装置。在设备的前面板上有:红色按钮,蓝色按钮和显示正整数的显示。单击红色按钮后,设备将显示的数字乘以2。单击蓝色按钮后,设备会从显示屏上的数字中减去一个。如果在某个时刻该数字停止为正数,则设备会发生故障。显示器可以显示任意大的数字。最初,显示屏显示数字n。
鲍勃希望在显示屏上显示数字m。为了达到这个结果,他必须达到的最小点击次数是什么?输入 输入的第一行和唯一一行包含两个不同的整数n和m(1≤n,m≤104),用空格分隔。
输出 打印一个数字 - 需要按下按钮才能获得数字m的数量n的最小次数。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
struct Node{
int val;
Node* Left;
Node* Right;
};
Node* GetNode(int val){
Node* newnode = new Node();
newnode->val = val;
newnode->Left = NULL;
newnode->Right = NULL;
return newnode;
}
int BFS(Node* root, int m){
int ctr = 0;
queue<Node*> qu;
qu.push(root);
while(!qu.empty()){
Node* tmp = qu.front();
qu.pop();
if(tmp->val == m) return ctr;
ctr++;
if(tmp->Left != NULL) qu.push(tmp->Left);
if(tmp->Right != NULL) qu.push(tmp->Right);
}
}
int main(void){
int n, m;
scanf("%d%d", &n, &m);
Node* root = GetNode(n);
Node* tmp;
queue<Node*> qu;
qu.push(root);
while(!qu.empty()){
tmp = qu.front();
qu.pop();
if(tmp->val == m) break;
tmp->Left = GetNode(2 * tmp->val);
qu.push(tmp->Left);
if(tmp->val-1 >= 0){
tmp->Right = GetNode(tmp->val - 1);
qu.push(tmp->Right);
}
}
printf("%d\n", BFS(root, m));
}
答案 0 :(得分:0)
while
中的main()
循环是一个无限循环。没有条件会终止该循环。你的程序不断为队列分配内存,直到它用完空间。
您的continue
应该是break
。尽管如此,由于它生成的指数级增长的队列,这个while()循环的效率非常低。
答案 1 :(得分:0)
您需要存储节点的级别(根级别:0),因为这将为您提供获取m所需的步骤。
struct Node{
int val;
Node* Left;
Node* Right;
int lev;
};
然后,getNode将再增加一个参数(级别):
Node* GetNode(int val,int l){
Node* newnode = new Node();
newnode->val = val;
newnode->lev = l;
newnode->Left = NULL;
newnode->Right = NULL;
return newnode;
}
树的根从0级开始:
Node* root = GetNode(n,0);
当你想得到一个新节点时,该等级将是父+1的级别:
node->Left = GetNode(value,(node->lev)+1);
你的休息时间不是最有效的,你应该在添加一个新节点时停止循环(值为tmp-> val * 2或tmp-> val-1),其中任何一个都是m(并且不要忘记更新tmp,你将用它来打印答案)。
使算法高效的另一个重要方面是知道应该在树中何时添加节点。其中一个是“如果它们是tmp-&gt; val-1小于或等于0(数字必须始终为正)。另外,如果节点高于m,那么它不应该增加,所以tmp-&gt ;只有在tmp-&gt; val&lt; m。
时才会创建left最后,如果你到达树中已有的数字,那么你应该添加该节点(这个验证是用!nit.count(x)完成的,这意味着“如果我的地图中没有任何x”)
//this if comes inmediatly after reading n and m
if (n==m){
cout<<0<<endl;
return 0;
}
while(!qu.empty()){
tmp = qu.front();
qu.pop();
if (!nit.count(2 * tmp->val) && (tmp->val<m)){
tmp->Left = GetNode(2 * tmp->val,tmp->lev+1);
//cout<<2 * tmp->val<<endl;
if ((2 * tmp->val)==m){
tmp=tmp->Left; break;
}
nit[2 * tmp->val]++;
qu.push(tmp->Left);
}
if(!nit.count(tmp->val-1) && (tmp->val-1 > 0)){
tmp->Right = GetNode(tmp->val - 1,tmp->lev+1);
//cout<<tmp->val-1<<endl;
if ((tmp->val-1)==m){
tmp=tmp->Right; break;
}
nit[tmp->val-1]++;
qu.push(tmp->Right);
}
}
现在你有了答案:
printf("%d\n",tmp->lev);
这是整个代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <queue>
using namespace std;
struct Node{
int val;
Node* Left;
Node* Right;
int lev;
};
Node* GetNode(int val,int l){
Node* newnode = new Node();
newnode->val = val;
newnode->lev = l;
newnode->Left = NULL;
newnode->Right = NULL;
return newnode;
}
int main(void){
int n, m;
map<int,int>nit;
scanf("%d%d", &n, &m);
if (n==m){
cout<<0<<endl;
return 0;
}
Node* root = GetNode(n,0);
nit[n++];
Node* tmp;
queue<Node*> qu;
qu.push(root);
while(!qu.empty()){
tmp = qu.front();
qu.pop();
if (!nit.count(2 * tmp->val) && (tmp->val<m)){
tmp->Left = GetNode(2 * tmp->val,tmp->lev+1);
//cout<<2 * tmp->val<<endl;
if ((2 * tmp->val)==m){
tmp=tmp->Left; break;
}
nit[2 * tmp->val]++;
qu.push(tmp->Left);
}
if(!nit.count(tmp->val-1) && (tmp->val-1 > 0)){
tmp->Right = GetNode(tmp->val - 1,tmp->lev+1);
//cout<<tmp->val-1<<endl;
if ((tmp->val-1)==m){
tmp=tmp->Right; break;
}
nit[tmp->val-1]++;
qu.push(tmp->Right);
}
}
printf("%d\n",tmp->lev);
}
对不起我的英语c: