问题 E: 【宽搜入门】巧妙取量

                                  问题 E: 【宽搜入门】巧妙取量

题目描述

  有三个容器,容量分别为 a,b,c(a> b > c ),一开始a装满油,现在问是否只靠abc三个容器量出k升油。如果能就输出“yes”,并且说明最少倒几次,否则输出“no”。例如:10升油在10升的容器中,另有两个7升和3升的空容器,要求用这三个容器倒油,使得最后在abc三个容器中有一个刚好存有5升油,问最少的倒油次数是多少?(每次倒油,A容器倒到B容器,或者A内的油倒完,或者B容器倒满。
 10 7 3
(10 0 0)
(3 7 0):第一次
(3 4 3):第二次
(6 4 0):第三次
(6 1 3):第四次
(9 1 0):第五次
(9 0 1):第六次
(2 7 1):第七次
(2 5 3):第八次,出现5了。

Input

【输入格式】
  有多组测试数据。
  输入a,b,c, k四个正整数( 100 ≥ a > b > c≥1 , 1≤k< 100 )

Output

【输出格式】
  如果能得到k就输出两行。
  第一行“yes”,第二行为最少的次数
  否则输出“no”

Sample Input

 

10 7 3 5

Sample Output

 

yes
8

AC代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
struct state{
	int a,b,c,step;
}s,e;
int a,b,c,k;
bool f[105][105][105];
 
int bfs(state x){
	queue<state> q;
	q.push(x);
	f[x.a][x.b][x.c]=true;
	while(!q.empty()){
		state cur=q.front();
		q.pop();
		if(cur.a==k||cur.b==k||cur.c==k){
			return cur.step;
		}
		if(cur.a>0&&cur.b<b){     //v1->v2
		  int t=min(cur.a,b-cur.b);
		  state temp;
		  temp.a=cur.a-t;
		  temp.b=cur.b+t;
		  temp.c=cur.c;
		  temp.step=cur.step+1;
		  if(!f[temp.a][temp.b][temp.c]){
		  	q.push(temp);
		  	f[temp.a][temp.b][temp.c]=1;
		  }
		}
		if(cur.a>0&&cur.c<c){     //v1->v3
		  int t=min(cur.a,c-cur.c);
		  state temp;
		  temp.a=cur.a-t;
		  temp.b=cur.b;
		  temp.c=cur.c+t;
		  temp.step=cur.step+1;
		  if(!f[temp.a][temp.b][temp.c]){
		  	q.push(temp);
		  	f[temp.a][temp.b][temp.c]=1;
		  }
		}
		if(cur.b>0&&cur.c<c){     //v2->v3
		  int t=min(cur.b,c-cur.c);
		  state temp;
		  temp.a=cur.a;
		  temp.b=cur.b-t;
		  temp.c=cur.c+t;
		  temp.step=cur.step+1;
		  if(!f[temp.a][temp.b][temp.c]){
		  	q.push(temp);
		  	f[temp.a][temp.b][temp.c]=1;
		  }
		}
		if(cur.b>0&&cur.a<a){     //v2->v1
		  int t=min(cur.b,a-cur.a);
		  state temp;
		  temp.a=cur.a+t;
		  temp.b=cur.b-t;
		  temp.c=cur.c;
		  temp.step=cur.step+1;
		  if(!f[temp.a][temp.b][temp.c]){
		  	q.push(temp);
		  	f[temp.a][temp.b][temp.c]=1;
		  }
		}
		if(cur.c>0&&cur.a<a){     //v3->v1
		  int t=min(cur.c,a-cur.a);
		  state temp;
		  temp.a=cur.a+t;
		  temp.b=cur.b;
		  temp.c=cur.c-t;
		  temp.step=cur.step+1;
		  if(!f[temp.a][temp.b][temp.c]){
		  	q.push(temp);
		  	f[temp.a][temp.b][temp.c]=1;
		  }
		}
		if(cur.c>0&&cur.b<b){     //v3->v2
		  int t=min(cur.c,b-cur.b);
		  state temp;
		  temp.a=cur.a;
		  temp.b=cur.b+t;
		  temp.c=cur.c-t;
		  temp.step=cur.step+1;
		  if(!f[temp.a][temp.b][temp.c]){
		  	q.push(temp);
		  	f[temp.a][temp.b][temp.c]=1;
		  }
		}
	}
	return -1;//可以倒0次!!! 
} 
int main(){
	while(~scanf("%d%d%d%d",&a,&b,&c,&k)){
		s.a=a,s.b=0,s.c=0,s.step=0;
		memset(f,0,sizeof(f));
		int ans=bfs(s);
		if(ans==-1) printf("no\n");
        else{
        	printf("yes\n%d\n",ans);
		}
	}
	return 0;
}

参考:https://blog.csdn.net/qq_39402039/article/details/78162027

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值