《算法笔记》8.2小节——搜索专题->广度优先搜索(BFS)问题 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
分析:这道题的做法和这节的问题A下面提示的有一些区别,这道题能做的操作只有把油从容器X倒到容器Y中,不可以从外面补充,也不可以把油直接倒掉。因此总共只有6种可能的操作:把油从a倒进b;把油从a倒进c;把油从b倒进c;把油从b倒进a;把油从c倒进b;把油从c倒进a.
搞清楚这点之后,用BFS就可以做了。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <map>
#include <set>
#include<unordered_map>
#define INF 0x3f3f3f3f
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,a) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#a<<"="<<(a)<<endl
#define db5(x,y,z,a,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#a<<"="<<(a)<<", "<<#r<<"="<<(r)<<endl
using namespace std;
typedef struct node
{
int cap_a,cap_b,cap_c,cnt_a,cnt_b,cnt_c,index;
}node;
node pour_a2b(node now,int a,int b)
{
node temp=now;
if(a==1&&b==2)
{
if(temp.cnt_a<temp.cap_b-temp.cnt_b)temp.cnt_b+=temp.cnt_a,temp.cnt_a=0;
else temp.cnt_a-=temp.cap_b-temp.cnt_b,temp.cnt_b=temp.cap_b;
}
else if(a==2&&b==3)
{
if(temp.cnt_b<temp.cap_c-temp.cnt_c)temp.cnt_c+=temp.cnt_b,temp.cnt_b=0;
else temp.cnt_b-=temp.cap_c-temp.cnt_c,temp.cnt_c=temp.cap_c;
}
else if(a==1&&b==3)
{
if(temp.cnt_a<temp.cap_c-temp.cnt_c)temp.cnt_c+=temp.cnt_a,temp.cnt_a=0;
else temp.cnt_a-=temp.cap_c-temp.cnt_c,temp.cnt_c=temp.cap_c;
}
temp.index=now.index+1;
return temp;
}
node pour_b2a(node now,int a,int b)
{
node temp=now;
if(a==2&&b==1)
{
if(temp.cnt_b<temp.cap_a-temp.cnt_a)temp.cnt_a+=temp.cnt_b,temp.cnt_b=0;
else temp.cnt_b-=temp.cap_a-temp.cnt_a,temp.cnt_a=temp.cap_a;
}
else if(a==3&&b==2)
{
if(temp.cnt_c<temp.cap_b-temp.cnt_b)temp.cnt_b+=temp.cnt_c,temp.cnt_c=0;
else temp.cnt_c-=temp.cap_b-temp.cnt_b,temp.cnt_b=temp.cap_b;
}
else if(a==3&&b==1)
{
if(temp.cnt_c<temp.cap_a-temp.cnt_a)temp.cnt_a+=temp.cnt_c,temp.cnt_c=0;
else temp.cnt_c-=temp.cap_a-temp.cnt_a,temp.cnt_a=temp.cap_a;
}
temp.index=now.index+1;
return temp;
}
int main(void)
{
#ifdef test
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
clock_t start=clock();
#endif //test
node beg;
int tar;
while(~scanf("%d%d%d%d",&beg.cap_a,&beg.cap_b,&beg.cap_c,&tar))
{
int f=0;
bool flag[101][101][101];
memset(flag,0,sizeof(flag));
if(max(beg.cap_a,max(beg.cap_b,beg.cap_c))<tar)printf("no\n");
else
{
beg.cnt_a=beg.cap_a;beg.index=0;
queue<node>que;que.push(beg);
flag[beg.cnt_a][beg.cnt_b][beg.cnt_c]=1;
while(!que.empty())
{
node fir=que.front(),temp=fir;que.pop();
if(temp.cnt_a==tar||temp.cnt_b==tar||temp.cnt_c==tar)
{
f=1;
printf("yes\n%d\n",temp.index);
break;
}
for(int i=1;i<=3;++i)
{
if(i<=2)
{
temp=pour_a2b(fir,i,i+1);
if(flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]==0)
flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]=1,que.push(temp);
temp=pour_b2a(fir,i+1,i);
if(flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]==0)
flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]=1,que.push(temp);
}
else
{
temp=pour_a2b(fir,1,3);
if(flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]==0)
flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]=1,que.push(temp);
temp=pour_b2a(fir,3,1);
if(flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]==0)
flag[temp.cnt_a][temp.cnt_b][temp.cnt_c]=1,que.push(temp);
}
}
}
if(!f)printf("no\n");
}
}
#ifdef test
clockid_t end=clock();
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
printf("\n\n\n\n\n");
cout<<"Total time:"<<endtime<<"s"<<endl; //s为单位
cout<<"Total time:"<<endtime*1000<<"ms"<<endl; //ms为单位
#endif //test
return 0;
}