题目大意:
给三个杯子,容量分别为A,B,C,A,B,C得关系为1<=A,B<=100,C<=max(A,B);
可以对A,B杯子做以下三个操作:
- FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
- DROP(i) empty the pot i to the drain;
- POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
要求输出最小的操作次数使得A或者B杯子中液体的容量为C,并输出每次的具体操作。
解题思路:
这是一道宽搜问题,在宽搜的过程中要标记每次入栈的元素的步数,上一层入栈元素的下标以及该元素入栈时做的操作类型
将杯子A,B作为一个整体!
初态为(v1,v2)
进行操作DROP(1)标记为1
进行操作DROP(2)标记为2
进行操作FILL(1),标记为3
进行操作FILL(2)标记为4
进行操作POUR(1,2)标记为5
进行操作POUR(2,1)标记为6
代码如下:
#include<stdio.h>
#include<string.h>
int a,b,c;
int res,flag=0;
int head=0,tail=0;
char opr[6][10]={{"DROP(1)"},{"DROP(2)"},
{"FILL(1)"},{"FILL(2)"},{"POUR(1,2)"},{"POUR(2,1)"}};
struct Pot{ //每一个入队列的状态
int v1; //A杯子里液体的体积
int v2; //B杯子里液体的体积
int type; //入栈时所作的操作的类型
int pre,step; //上一层父节点在队列中的序号
};
Pot pot,pots[10010];
int mark[110][110]; //标记每一个状态(A,B杯子里的液体的体积),
void drop(int num){
if(num==1){
pot.v1=0;
pot.v2=pots[head].v2;
pot.pre=head;
pot.type=1;
pot.step=pots[head].step+1;
}
else if(num==2){
pot.v1=pots[head].v1;
pot.v2=0;
pot.pre=head;
pot.type=2;
pot.step=pots[head].step+1;
}
}
void fil(int num){
if(num==1){
pot.v1=a;
pot.v2=pots[head].v2;
pot.pre=head;
pot.type=3;
pot.step=pots[head].step+1;
}
else if(num==2){
pot.v1=pots[head].v1;
pot.v2=b;
pot.pre=head;
pot.type=4;
pot.step=pots[head].step+1;
}
}
void pour(int num1,int num2){
if(num1==1 && num2==2){
if(pots[head].v1+pots[head].v2<b){
pot.v1=0;pot.v2=pots[head].v1+pots[head].v2;
pot.pre=head;
pot.type=5;
pot.step=pots[head].step+1;
}
else{
pot.v1=pots[head].v1+pots[head].v2-b;
pot.v2=b;
pot.pre=head;
pot.type=5;
pot.step=pots[head].step+1;
}
}
else if(num1==2 && num2==1){
if(pots[head].v1+pots[head].v2<a){
pot.v1=pots[head].v1+pots[head].v2;
pot.v2=0;
pot.pre=head;
pot.type=6;
pot.step=pots[head].step+1;
}
else{
pot.v1=a;
pot.v2=pots[head].v1+pots[head].v2-a;
pot.pre=head;
pot.type=6;
pot.step=pots[head].step+1;
}
}
}
void push(){
pots[tail].v1=pot.v1;
pots[tail].v2=pot.v2;
pots[tail].type=pot.type;
pots[tail].pre=pot.pre;
pots[tail++].step=pot.step;
}
void bfs(){
head=tail=0;
pots[tail].v1=pots[tail].v2=0;
pots[tail].type=0;
pots[tail].pre=pots[tail++].step=0;
while(head<tail){
drop(1);
if(mark[pot.v1][pot.v2]==0){
mark[pot.v1][pot.v2]=1;
push();
if(pot.v1==c || pot.v2==c){
break;
}
}
drop(2);
if(mark[pot.v1][pot.v2]==0){
mark[pot.v1][pot.v2]=1;
push();
if(pot.v1==c || pot.v2==c){
break;
}
}
fil(1);
if(mark[pot.v1][pot.v2]==0){
mark[pot.v1][pot.v2]=1;
push();
if(pot.v1==c || pot.v2==c){
break;
}
}
fil(2);
if(mark[pot.v1][pot.v2]==0){
mark[pot.v1][pot.v2]=1;
push();
if(pot.v1==c || pot.v2==c){
break;
}
}
pour(1,2);
if(mark[pot.v1][pot.v2]==0){
mark[pot.v1][pot.v2]=1;
push();
if(pot.v1==c || pot.v2==c){
break;
}
}
pour(2,1);
if(mark[pot.v1][pot.v2]==0){
mark[pot.v1][pot.v2]=1;
push();
if(pot.v1==c || pot.v2==c){
break;
}
}
head++;
}
if(head==tail){
printf("impossible\n");
flag=1;
}
}
int main(){
while(~scanf("%d%d%d",&a,&b,&c)){
flag=0;
memset(mark,0,sizeof(mark));
bfs();
if(flag)
continue;
tail--;
printf("%d\n",pots[tail].step);
int tmp=tail;
int opera[1000],num=0;
while(pots[tmp].type!=0){
opera[num++]=pots[tmp].type;
tmp=pots[tmp].pre;
}
for(int i=num-1;i>=0;i--){
printf("%s\n",opr[opera[i]-1]);
}
}
}