bfs题解

Vjudge

A - Catch That Cow

John和奶牛分别在数轴的n和k上,john去找奶牛且奶牛不会动
john有三种移动的方式
1.向前一格
2.向后一格
3.从点x移动到点2*x
求john到奶牛的位置最少需要几步
对于n>k的情况,John只能一步步往后退去找牛,所以步数为n-k
对于n==k的情况,John不用动,这种情况可以和第一种情况合并
对于n<k的情况,通过bfs去搜索最少需要几步

#include<iostream>
#include<queue>
using namespace std;

const int N=1e5+5;
int n,k;
int vis[N];   //标记是否走过该点 
int step[N];  //记录步数 

bool check(int x){
      //判断这个点是否在范围内 
	if(x>=0 && x<=1e5 ) 
		return true;
	return false;
}

int bfs(){
   
	queue <int> q;
	int start,next;
	step[n]=0;//在n点的时候步数为0 
	q.push(n);
	vis[n]=1;//标记n点走过 
	while(!q.empty()){
   
		start = q.front();
		if(start==k){
      //  到达牛的位置  退出 
			return step[start];
		}
		q.pop();//记得取出后删除 
		for(int i=0;i<3;i++){
     //三种走法 
			if(i==0){
   //第一种走法,向前一格 
				next=start+1;
			}
			if(i==1){
   //第二种走法,向后一格 
				next=start-1;
			}
			if(i==2){
   //第三种走法,从x移到2*x 
				next=start*2;
			}
			if(check(next) && vis[next]==0){
   //判断在范围内且没有走过 
				q.push(next);
				step[next]=step[start]+1;  //步骤+1 
				vis[next]=1;//标记走过 
			}
		}
	}
	return -1;
}

int main(){
   
	cin >> n >> k; 
	if(n>=k){
      //这种情况下只能一步步后退 
		cout <<n-k << endl;
	} 
	else{
   
		cout<<bfs()<<endl;
	}
	return 0;
}

B - Find The Multiple

给一个n,要求求出一个由0和1构成的数字,使得n能被这个数整除
如果给定n有多个解,其中任何一个都是可以接受的。
从1 开始,在后面依次添加0或者1,即x -> x*10x -> x*10+1
当找到一个数能够整除n时,就结束搜索
要注意的是,这题要用ll

#include<iostream>
#include<queue>
typedef long long ll;
using namespace std;

int n;

void bfs(int n){
   
	queue<ll>q;//注意要用ll 
	q.push(1);
	while(!q.empty()){
   
		ll x=q.front(); 
		q.pop();
		if(x%n==0){
   //找到一个数能够整除n 
			cout << x << endl;//输出这个数
			return; 
		}
		q.push(x*10);//添加0 
		q.push(x*10+1);//添加1 
	} 
}

int main(){
   
	while(cin >> n && n){
   
	 	bfs(n);
	}
	return 0;
}

C - Prime Path

给你t组数据
每组数据给你两个四位数,每次操作只能修改一位数字
要求每次修改后的四位数都是质数
问最少花费(也就是操作次数)几次可以将第一个四位数修改成为第二个四位数
如何修改数字呢?每次将数拆成个十百千四位
改变其中一个数字,在将这四个数字组成四位数
通过判断这个数是不是四位数,并且是不是素数来剪枝
如何判断其是否为素数?埃氏筛

#include<iostream>
#include<queue>
#include<string.h> 
using namespace std;

const int N=1e4+5;
int n,m;
int vis[N];
int prime[N];//素数表 

struct node{
   
	int x;//四位数的值 
	int cnt;//当前四位数所用的花费 
};

void isprime(){
   
	memset(prime,0,sizeof(prime)); // 初始化每一个都是素数 
	prime[0]=1;//不是素数 
	prime[1]=1;//不是素数 
	for(int i=2;i<N;i++){
     // 埃氏筛法判断素数 
		if(!prime[i]){
   
			for(int j=2*i;j<N;j=j+i){
   
				prime[j]=1;  //不是素数 
			}
		}
	} 
}

int check(int x){
   //判断是否是四位数并且是素数 
	if(!prime[x] && x>=1000 && x<=9999){
   
		return 1;
	}
	else
		return 0;
} 

void bfs()
{
   
	node st,next;
	queue<node>q;
	st.x=n;
	st.cnt=0;//初始花费为0 
	vis[st.x]=1;//标记这个数字已经出现 
	q.push(st);
	int a[4];//用来存四位数 
	while(!q.empty()){
   
		st=q.front();
		q.pop();
		a[0]=st.x%10;//个位
		a[1]=st.x/10%10;//十位 
		a[2]=st.x/100%10;//百位 
		a[3]=st.x/1000%10; //千位
		for(int i=0;i<4;i++){
   //对每一个数字进行改变 
			int temp=a[i];//标记用于回溯 
			for(int j=0;j<=9;j++){
   //数字可以是0~9 
				if(a[i]!=j){
   
					a[i]=j;
					next.x=a[3]*1000+a[2]*100+a[1]*10+a[0]; // 新的数字 
					if(next.x==m){
     //与m相等,输出答案结束循环 
						cout << st.cnt+1 << endl;//输出花费,也就是最少操作数 
						return ;
					}
					if(check(next.x) && !vis[next.x]){
    //判断合法 
						next.cnt=st.cnt+1;//花费增加 
						vis[next.x]=1;//标记已经出现 
						q.push(next);
					}
				}
			}
			a[i]=temp; // 回溯 
		} 
	}
	cout << "Impossible" << endl;//无法修改成为目标四位数 
	return;
}

int main()
{
   
	int t;
	cin>>t;
	isprime();//埃氏筛打表 
	while(t--){
   
		memset(vis,0,sizeof(vis));//初始化 
		cin>>n>>m;
		if(n==m){
   //输入的时候两个数就是相等的 
			cout << 0 << endl;
		}
		else
			bfs();
	}
	return 0;
}

D - Pots

有两杯水,容量分别为a,b
你可以进行三种操作
1.FILL(i) 装满水
2.DROP(i) 水全部倒掉
3.POUR(i,j) i中的水倒入j
通过最少的操作次数,使得一个罐子里恰好有c升水
同时要输出操作方法
根据题意,可以知道一共有六种操作:
FILL(1) FILL(2) DROP(1) DROP(2) POUR(1,2) POUR(2,1)
要注意的是要在结构体中开一个数组用来记录操作

#include<iostream>
#include<queue>
using namespace std;

const int N=105; 
int a,b,c;
bool vis[N][N];
string path[] = {
   "FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};//六种操作 

struct node {
   
   int a, b;//两个水杯中的水的多少 
   int path[N];//存储路径
   int step;//操作步数 
};

void pr(int step,int p[]){
   //输出 
   cout << step << endl;//输出操作数 
   for(int i=0; i<step; i++)
       cout << path[p[i]] << endl;//输出每一步的操作 
}

void bfs(){
   
   queue<node> q; 
   node st;
   st.a=0;//a水杯初始没有水 
   st.b=0;//b水杯初始没有水 
   st.step=0;//输出操作数为0 
   q.push(st);
   vis[st.a][st.b] = <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值