链接点击打开链接
倒水问题。bfs其实就解决了。
但是很早以前我一开始遇到的时候我还没有那种思想,但是还是ac掉了。
思路
对于一个a,一个b,通过倒水,可以得到什么?
在a,b互质的情况下,可以得到0~max(a,b)之间的所以数字。如果不互质,设x为他们的最大公约数,a/x 和b/x是互质的,那么a/x和b/x 获得的所有数字*x即a,b可以获得的数字。
所以可以令x=gcd(a,b),那么获得(0~max(a/x,b/x))*x.的数。
那么我们获得这些数的过程只有2种
第一:
装b
倒入a
如果a满,a倒空
如果b非空,b继续倒入a
第二:即把a,b位置互换
两种操作得到的数的顺序是正好颠倒过来的,所以我们要找出最小操作,那么如果进行了操作1那么不可能进行操作2,因为这样会
相互抵消。其次我们只需要将操作1进行到底和操作2进行到底,判断我们需要的数字在哪个地方出现的早就选哪里。如果没出现过
则判不可能(或者在一开始就判断)
if(end>y&&end>x) printf("impossible\n");
else if(((x%y==0||y%x==0)&&(end%y!=0&&end%x!=0))||(x%2==0&&y%2==0&&end%2!=0)) printf("impossible\n");
同时记录操作,输出即可。
代码
#include <stdio.h>
/*
1=p1装水;
2=p2装水;
3=p1->p2;
4=p2->p1;
5=p1倒水;
6=p2倒水;
*/
int main(){
int x,y,end;
while(scanf("%d %d %d",&x,&y,&end)!=EOF){
int p[100000],q[100000];
int i=0,j=0;
if(end>y&&end>x) printf("impossible\n");
else if(((x%y==0||y%x==0)&&(end%y!=0&&end%x!=0))||(x%2==0&&y%2==0&&end%2!=0)) printf("impossible\n");
else{
int now=0;
while(now!=end&&x!=end){
now=now+x;
p[i++]=1;
p[i++]=3;
if(now==end) break;
while(now>y){
now=now-y;
if(now==end) break;
p[i++]=6;
p[i++]=3;
}
if(now==end) break;
}
if(x==end) p[i++]=1;
now=0;
while(now!=end&&y!=end){
now=now+y;
q[j++]=2;
q[j++]=4;
if(now==end) break;
// printf("j=%d,now=%d",j,now);
// printf("j==%d",j);
while(now>x){
now=now-x;
if(now==end) break;
q[j]=5;
j=j+1;
q[j]=4;
j=j+1;
}
if(now==end) break;
}
if(y==end) q[j++]=2;
// printf("%d %d",i,j);
if(i<=j){
printf("%d\n",i);
for(j=0;j<i;j++){
if(p[j]==1)printf("FILL(1)\n");
if(p[j]==3)printf("POUR(1,2)\n");
if(p[j]==6)printf("DROP(2)\n");
}
}else{
printf("%d\n",j);
for(i=0;i<j;i++){
if(q[i]==2)printf("FILL(2)\n");
if(q[i]==4)printf("POUR(2,1)\n");
if(q[i]==5)printf("DROP(1)\n");
}
}
}
}
}