搜索与回溯(一本通)基础篇

第一类:就是例题,直接搜索完了打标记退回就行了

组合的输出

第一种方法:字典序,典型的DFS,打标记

#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
using namespace std;
int m,n;
int a[21]={1},b[21];
void print(){
	for(int i=1;i<=n;i++) cout<<"  "<<a[i];
	cout<<endl;
}
int search(int x){
	for(int i=a[x-1];i<=m;i++)
		if(!b[i]){
			a[x]=i;
			b[i]=1;
			if(x==n) print();
			else search(x+1);
			b[i]=0;
		}
	}
	
	

int main(){
cin>>m>>n;

search(1);
return 0;
}

第二种方法:二进制处理,但是好像不是按照字典序

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
int tot;
//但是这样不是按照字典序 
void print(int n,int k){
	for(int i=0;i<(1<<n);i++){
		int num=0,kk=i;
		while(kk){
			kk=kk&(kk-1);
			num++;
		}
		if(num==k){
			for(int j=0;j<n;j++){
				if(i&(1<<j)){
					cout<<"  "<<j+1;
				}
			}
			tot++;
			cout<<endl;
		}
	}
}
int main(){
	int n,k;
	cin>>n>>k;
	print(n,k);cout<<tot<<endl;
return 0;
}

  

一、自然数的拆分,这里使用的方法与因子分解哪里差不多,但是注意用这个方法的因子分解要求数据很小

int n,a[10001]={1},total;  //这里如果没有将数组a全部赋值为1是不行的 
void print(int t){
	cout<<n<<"=";
	for(int i=1;i<=t-1;i++) cout<<a[i]<<"+";
	cout<<a[t]<<endl;
	total++;
} 
int search(int s,int t){ 
	for(int i=a[t-1];i<=s;i++){
		if(i<n){ //注意条件 
			a[t]=i;
			s-=i;   //保留结果 
			if(s==0) print(t); //到达终点 
				else search(s,t+1);
			s+=i; //回溯 
		}
	}
}

int main(){
	cin>>n;

	search(n,1); 
	return 0;
}

二、 分为互质组(可能要求数据量比较小?)

其实逻辑理清楚了就很好写,而且这个不属于回溯的范围,就是逻辑题目,每一次递归就产生一个新的组,如果这个组是空的,就放一个进去,然后看剩下的所有的有没有和里面的都互质的,有就放,这就是一个组,然后处理剩下的就行了

int num,n,len;
int flag=0;
int vis[11],map[11][11], a[11];
bool check(int a,int b){
	for(int i=2;i<=a/2&&i<=b/2;i++){
		if(a%i==0&&b%i==0) return false;
	}
	return 1;
}
void dfs(int k){
	num=k-1;//为什么要是k-1因为最后会递归到k+1才会退出 
	if(len==0) return ;
	int i; 
	if(map[k][0]==0){ //第K组没有数据
	 for(i=flag+1;i<=n;i++){
	 	if(vis[i]==0){
	 		map[k][1]=a[i];
	 		map[k][0]++;
	 		vis[i]=1;
	 		len--;//减少一个
			 flag=i;//下次从这里开始
			 break; 
			  
		 }
	 }	
	}       //一定要注意flag的运用!!!!避免多次重复计算 
 //如果这个分组有数据 
 //注意这里没有else!!!!! 
		for(i=flag+1;i<=n;i++){
			if(vis[i]==0){
				bool yes=1;//判断与这个分组里里面的数据是不是互斥
				for(int j=1;j<=map[k][0];j++){
					if(check(map[k][j],a[i])==0){
						yes=0;
						break;
					}
				} 
				if(yes==1){
					map[k][0]++;
					map[k][map[k][0]]=a[i];
					vis[i]=1;
					len--;
				}
			}
		}
		
	
	dfs(k+1);  //进行下一组 
		return ;
}
int main(){
	cin>>n;
	len=n;
	for(int i=1;i<=n;i++) cin>>a[i];
	memset(vis,0,sizeof(vis));
	memset(map,0,sizeof(map)); 
	dfs(1);
	cout<<num<<endl;
}

四、单词接龙

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。

当时做的时候觉得这道题好难噢,注意细节和思路!!!

 

我草,用这个代码的话根本不能解决不重合的问题,照样是可以的(不懂)

string str[1000];
int n,vis[1001]={0},length=0;
//检查两个字符串的重叠部分 
inline int check(string a,string b){ 
	
	int p=min(a.length(),b.length());
	for(int i=1;a.length()==1? i<=p:i<p;i++){   //!! 
		bool flag=1;//这个位置错了!! 
		
		//这个三目运算符看懂,要特判字符串是不是只有一个单词,是的话下面循环会直接退出
		//如果不是为1那么为i<p因为从0开始
		for(int j=0;j<i;j++){
			if(a[a.length()-i+j]!=b[j]){//如果不匹配,注意这个是a.length()-i+j 
				flag=0;
				break;
			}
		} 
		if(flag==1) return i; //相同部分的长度 
	}
	return 0;
}
//接下来是搜索过程
void dfs(string s,int length_now){
	length=max(length,length_now);//每次搜索都要特判
	for(int i=1;i<=n;i++){ //对每个字符串都要判断(暴力搜索)
	if(vis[i]>1) continue;//如果使用了两次就退出
	else{
		int add=check(s,str[i]);//不用纠结上面判断a.length()==0,因为这是个循环,每个字符串都会被判断
		if(add!=0){
			vis[i]++;
			dfs(str[i],length_now+str[i].length()-add);//新的长度为现在长度加字符串长度-重叠长度
			vis[i]--;//回溯 
		} 
	} 
		
	} 
	
} 


int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>str[i];
	cin>>str[n+1];
	dfs(str[n+1],1);
	cout<<length<<endl; 
	
	
return 0;
}

 

1212:LETTERS

 

 换了之后搜索,然后马上换回来,one of例题

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
int r,s,ans;
char mp[30][30];
int vis[30][30];
int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void change(char x){
	for(int i=1;i<=r;i++){
		for(int j=1;j<=s;j++){
			if(mp[i][j]==x) vis[i][j]=!vis[i][j];
		}
	}
}
void dfs(int x,int y,int tot){
	ans=max(ans,tot);
	for(int i=0;i<4;i++){
		int xx=x+dis[i][0];
		int yy=y+dis[i][1];
		if(xx>=1&&xx<=r&&yy>=1&&yy<=s&&!vis[xx][yy]){
			
			change(mp[xx][yy]);
			dfs(xx,yy,tot+1);
			change(mp[xx][yy]);
		}
	}
}
int main(){
	cin>>r>>s;
	for(int i=1;i<=r;i++){
		scanf("%s",mp[i]+1);
	}
	ans=1;
	change(mp[1][1]);
	dfs(1,1,1);
	cout<<ans<<endl;
return 0;
}

  

1218:取石子游戏

假设石子数目为(a,b)且a >= b,如果[a/b] >= 2则先手必胜,如果[a/b]<2,那么先手只有唯一的一种取法。[a/b]表示a除以b取整后的值。

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
using namespace std;
int a,b;
bool get(int x,int y){
	if(x<y) swap(x,y);
	if(x/y>=2||x==y) return 1;
	else return !get(y,x-y);//这是辗转相除法的思想 ,注意取反 
} 

int main(){
	/*while(cin>>a>>b){
		if(a==0&&b==0) break;
		if(a<b) swap(a,b);
		if(a/b<2){
			
		
		for(int i=1;a>=0&&b>=0;i++){
			if(a<b) swap(a,b);
			int k;
			for(k=1;a-k*b>=0;k++);
			a-=(k-1)*b;
			if(a==0||b==0){
				if(i%2==1) cout<<"win"<<endl;
				else cout<<"lose"<<endl;
				break;
			}
		
		}
		}
		else {
			cout<<"win"<<endl;
		}
	
}
*/
//我不太理解这道题,明明就可以取更多的,为什么不取更多,最优取法是什么?
//本题的解法挺简单,但是我还是不不知道为什么我上面的写法是错误的; 
 while(cin>>a>>b){
 	if(a==0&&b==0) break;
 	if(get(a,b)) cout<<"win"<<endl;
 	else cout<<"lose"<<endl; 
 } 
return 0;
}

  

1222:放苹果

要么全不放,要么都放一个再说,注意是没苹果了或者只有一个盘子了才返回1

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<cstdlib>
using namespace std;
int find(int m,int n){
	if(m==0||n==1) return 1;
	else if(n>m) return find(m,m);
	else return find(m,n-1)+find(m-n,n);
}
int main(){
int sum;cin>>sum;
int x,y;
while(sum--){
	cin>>x>>y;
	cout<<find(x,y)<<endl;
}
return 0;
}

  

 

1213:八皇后问题

例题,写一次吧,三个数组用来判断

a[]是用来记录结果的,b[]是用来表示这个皇后有没取过,c[]是正对角线,d[]是斜对角线

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
int a[10],b[20],c[20],d[20];
int ans;
void print(){
	cout<<"No. "<<++ans<<endl;
	for(int i=1;i<=8;i++){
		for(int j=1;j<=8;j++){
			if(i==a[j]) cout<<"1 ";
			else cout<<"0 ";
		}
		cout<<endl;
	}
}
//a[]是用来记录结果的,b[]是用来表示这个皇后有没取过,c[]是正对角线,d[]是斜对角线
void dfs(int x){
	for(int i=1;i<=8;i++){
		if(!b[i]&&!c[x+i]&&!d[x-i+7]){ //一个是列, 
			b[i]=1;
			c[x+i]=1;
			d[x-i+7]=1;
			a[x]=i;
			if(x==8) print();
			else dfs(x+1);
			b[i]=0;
			c[x+i]=0;
			d[x-i+7]=0;
		}
	}
}
int main(){
	dfs(1);
return 0;
}

  

1216:红与黑

这个题目就没有回溯了,因为是求的最大值,而不是所有的值,全都试一遍总能找到

#include<iostream>
#include<cstring>
using namespace std;
char a[21][21];
int aa[21][21],pd[21][21],m,n,sum;
int l[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
int search(int x,int y){
	int nx,ny;
	for(int i=0;i<4;i++){
		nx=x+l[i][0];ny=y+l[i][1];
		if(nx>=0&&nx<n&&ny>=0&&ny<m&&aa[nx][ny]&&(!pd[nx][ny])){
			pd[nx][ny]=1;
			sum++;
			search(nx,ny);
		}
	}
	
}



int main(){
	for(;;){
		memset(aa,0,sizeof(aa));
		memset(pd,0,sizeof(pd));
		int x,y;sum=1;
		cin>>m>>n;
		if(m==0&&n==0) break;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++) {
				cin>>a[i][j];
				if(a[i][j]=='@') {x=i;y=j;aa[x][y]=1;
				}
				if(a[i][j]=='.') aa[i][j]=1;
				if(a[i][j]=='#') aa[i][j]=0;
			}
		}
		pd[x][y]=1;
		search(x,y);
		cout<<sum<<endl;
	}
	return 0;
}

  

1215:迷宫

这也是不需要回溯的,因为只需要判断能不能走得到,而不涉及方案的

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
using namespace std;
int k,n;
int dis[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int vis[101][101];
char map[101][101];
int sx,sy,ex,ey;
bool ok=0;
void find_way(int x,int y){
	vis[x][y]=1;
	for(int i=0;i<4;i++){
	int xx=x+dis[i][0];
	int yy=y+dis[i][1];
	if(xx>=0&&xx<n&&yy>=0&&yy<n&&!vis[xx][yy]){
		vis[xx][yy]=1;
		if(xx==ex&&yy==ey){
			ok=1;
			cout<<"YES"<<endl;
			return;
		}
		else find_way(xx,yy);
		
	}
}
}
int main(){
	cin>>k;
	char x;
	while(k--){
		memset(vis,0,sizeof(vis));
		memset(map,0,sizeof(map));
		cin>>n;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++) {
				cin>>map[i][j];
				if(map[i][j]=='#') vis[i][j]=1;
			}
		}
		ok=0;
		cin>>sx>>sy>>ex>>ey;
		if(map[sx][sy]=='#'||map[ex][ey]=='#') {
			cout<<"NO"<<endl;
			continue;
		}
		find_way(sx,sy);
		if(!ok) cout<<"NO"<<endl;
	}
	
return 0;
}

  

1217:棋盘问题   

1219:马走日(做法一样的)

这里求的是方案数量,所以要回溯,需要注意的是通过下标直接控制了行

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
using namespace std;
char map[101][101];
int num,k,n;
int vis[101];
void dfs(int x,int step){
	if(step==k) {num++;return;} 
	for(int i=x;i<=n;i++){  //这里的技巧!!!!i=x就直接避免了x相同的可能性 
		for(int j=1;j<=n;j++){
			if(map[i][j]=='#'&&!vis[j]) {
				vis[j]=1;
				dfs(i+1,step+1);//这里的i是+1!!!!!不然就是可能在同一行!!!!不需要在参数中加入列,直接枚举即可 
				vis[j]=0; //在这里面回溯 
			}
				
		}
	}

}


int main(){
	char x;
	while(cin>>n>>k){
		num=0;
		memset(vis,0,sizeof(vis));
		if(n==-1&&k==-1) break;
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			cin>>map[i][j];
		}
		dfs(1,0);
		//step的初值是0!!!! 
	cout<<num<<endl;
	}
return 0;
}

  

广度优先搜索(一本通基础篇)

首先是例题:

1329:【例8.2】细胞

在函数里面定义的队列,因为是求的个数,所以函数用一次就是一个细胞ps.节点队列学学

1249:Lake Counting(和这个做法一模一样)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,sum;
char a[301][301];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

struct node{
	int x,y;
};
void bfs(int x,int y){
	queue<node> q;
	a[x][y]='0';
	node c;c.x=x;c.y=y;
	q.push(c);
	while(!q.empty()){
		node d=q.front();
		for(int i=0;i<4;i++){
			int xx=d.x+dir[i][0];
			int yy=d.y+dir[i][1];
			if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]!='0'){
				a[xx][yy]='0';
				node newo;
				newo.x=xx;
				newo.y=yy;
				q.push(newo);
			}
		}
		q.pop();
	} 
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) cin>>a[i][j];
	}
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++){
		if(a[i][j]!='0'){
			sum++;
			bfs(i,j);
		}
	}
	cout<<sum<<endl;
	return 0;
}

  

1330:【例8.3】最少步数

1251:仙岛求药(和这个做法一模一样)

也很简单,就是节点多了一个参数:步数ps.节点初始化函数书写

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int x,y,step;
    node(){}
    node(int x1,int y1,int step1):x(x1),y(y1),step(step1){}
 
};
const int N=150;
int u[12][2]={{1,2},{1,-2},{-1,2},{-1,-2},{-2,-1},{-2,1},{2,1},{2,-1},{2,2},{-2,-2},{2,-2},{-2,2}};
int vis[N][N];
int a,b,c,d;
void bfs(int x,int y)
{
    memset(vis,0,sizeof(vis));
    vis[x][y]=1;
    queue<node>Q;
    Q.push(node(x,y,0));
    while(!Q.empty()){
        node a=Q.front();
        Q.pop();
        for(int i=0;i<12;i++){
            int xx=a.x+u[i][0];
            int yy=a.y+u[i][1];
            if(xx>=1&&xx<=100&&yy>=1&&yy<=100&&(vis[xx][yy]==0)){
                vis[xx][yy]=1;
                Q.push(node(xx,yy,a.step+1));
                if(xx==1&&yy==1){
                    cout<<a.step+1<<endl;
                    return;
                }
            }
        }
    }
 
}
int main()
{
    cin>>a>>b>>c>>d;
    bfs(a,b);
    bfs(c,d);
    return 0;
}

  

1248:Dungeon Master

三维的迷宫,不难,和二维的一样,注意细节就好

int summ;
int l,n,m;
bool ok;
int dir[6][3]={{1,0,0},{-1,0,0},{0,1,0,},{0,-1,0},{0,0,-1},{0,0,1}};
struct node{
	int l,x,y;
	int step;
};
node start,end;
char map[50][50][50];
bool vis[50][50][50];
void bfs(int ll,int xx,int yy,int step){
	queue<node> p;
	node d;
	d.l=ll;d.x=xx;d.y=yy;d.step=step;
	map[ll][xx][yy]='#';
	p.push(d);
	vis[ll][xx][yy]=1;
	while(!p.empty()){
		node s=p.front();
		for(int i=0;i<6;i++){
			int lll=s.l+dir[i][0];int xxx=s.x+dir[i][1];int yyy=s.y+dir[i][2];
			
			if(lll>-1&&lll<l&&xxx>-1&&xxx<n&&yyy>-1&&yyy<m&&map[lll][xxx][yyy]=='.'&&vis[lll][xxx][yyy]==0){
				if(lll==end.l&&xxx==end.x&&yyy==end.y) {
				summ=s.step+1;
				ok=1;
				return;
			}
				node ss;
				
				map[lll][xxx][yyy]='#';
				vis[lll][xxx][yyy]=1;
				ss.l=lll;ss.x=xxx;ss.y=yyy;ss.step=s.step+1;
				p.push(ss);
				
			}
			
		}
		p.pop();
	}
} 

也是三维搜索:

hud 1240 Asteroids!.cpp

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
typedef long long LL;
//三维BFS
struct node{
	int x,y,z;
	int num;
};
int dis[6][3]={{0,1,0},{0,-1,0},{1,0,0},{-1,0,0},{0,0,1},{0,0,-1}};
int n;
int sx,sy,sz,ex,ey,ez;
int mp[12][12][12];
int step[12][12][12];
int tot=0;
void bfs(int z,int x,int y){
	node a;
	a.x=sx;a.y=sy;a.z=sz;
	a.num=0;
	step[sz][sx][sy]=0;
	queue<node> q;
	q.push(a);
	while(!q.empty()){
		node u=q.front();
		q.pop();
		//先判断
		if(u.x==ex&&u.z==ez&&u.y==ey){
			tot=u.num;
			return;
		} 
		for(int i=0;i<6;i++){
			int xx=u.x+dis[i][0];
			int yy=u.y+dis[i][1];
			int zz=u.z+dis[i][2];
			if(xx>=0&&xx<n&&yy>=0&&yy<n&&zz>=0&&zz<n&&mp[zz][xx][yy]!=INF){
				if(step[zz][xx][yy]>step[u.z][u.x][u.y]+1){
					step[zz][xx][yy]=step[u.z][u.x][u.y]+1;
					mp[zz][xx][yy]=INF;
					node next;
					next.x=xx;next.y=yy;next.z=zz;
					next.num=u.num+1;
					q.push(next);
				}
			}
		}
	}
}
int main(){
	char st[21],ed[21],op;
	while(scanf("%s %d",st,&n)!=EOF){
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				for(int z=0;z<n;z++){
					cin>>op;
					if(op=='X') mp[i][j][z]=INF;
					if(op=='0') mp[i][j][z]=1;
					step[i][j][z]=INF;
				}
			}
		}
		cin>>sx>>sy>>sz>>ex>>ey>>ez;
		cin>>ed;
		tot=0;
		bfs(sz,sx,sy);
		if(step[ez][ex][ey]!=INF){
			cout<<n<<" "<<tot<<endl;
		}
		else cout<<"NO ROUTE"<<endl;
	}
	
	
return 0;
}

  

1250:The Castle

这道题就特殊在输入了,不过也没什么,判断能不能联通一个&就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 51
#define MOD 2520
#define E 1e-12
using namespace std;
int n,m;
int a[N][N];
int b[4]={1,2,4,8};
bool vis[N][N];
int sum,maxx;
int dir[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
struct node
{
    int x;
    int y;
}q[N*100];
void bfs(int x0,int y0)
{
    int head=1,tail=1;
    int cnt=1;
 
    vis[x0][y0]=1;
    q[tail].x=x0;
    q[tail].y=y0;
    tail++;
 
    while(head<tail)
    {
        int x=q[head].x;
        int y=q[head].y;
        for(int i=0;i<4;i++)
        {
            int nx=x+dir[i][0];
            int ny=y+dir[i][1];
            if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&vis[nx][ny]==0&&(a[x][y]&b[i])==0)
            {
                cnt++;
                vis[nx][ny]=1;
                q[tail].x=nx;
                q[tail].y=ny;
                tail++;
            }
        }
        head++;
    }
    if(cnt>maxx)
        maxx=cnt;
    sum++;
}
int main()
{
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
 
     for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(vis[i][j]==0)
                bfs(i,j);
    printf("%d\n%d\n",sum,maxx);
    return 0;
}

  

六、抓住那头牛

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0≤N≤100000),牛位于点K(0≤K≤100000)。农夫有两种移动方式:

1、从X移动到X-1或X+1,每次移动花费一分钟

2、从X移动到2*X,每次移动花费一分钟

假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

int num,head,tail;
int n,m;
int vis[N];
int dir[2]={1,-1};
int f[N*2][2];
void find(int x,int y){
	
	head=1;tail=1;
	f[1][0]=x;f[1][1]=0;
	vis[x]=1;
	tail++;
while(head<tail){
	int x0=f[head][0];
	if(x0==y) {
		cout<<f[head][1]<<endl;
		return ;
	}
	int xx;
	for(int i=0;i<2;i++){
			 xx=x0+dir[i]; 
			if(xx>=0&&xx<1000001&&vis[xx]==0){
				
				f[tail][0]=xx;
				f[tail][1]=f[head][1]+1;
				vis[xx]=1;
				tail++;
			}
		}
		xx=x0*2;
		if(xx>=0&&xx<100001&&vis[xx]==0){
			f[tail][0]=xx;
				f[tail][1]=f[head][1]+1;
				vis[xx]=1;
				tail++;
		} 
	
	head++;
}
}
int main(){
	cin>>n>>m;
	if(n>m) cout<<n-m<<endl;
	else {
		find(n,m);
	}
    
return 0;
} 

  

 
 posted on 2020-02-06 14:19  shirlybabyyy  阅读(30)  评论(0编辑  收藏  举报