題目意思:給出兩個杯子容積,初始都為空杯子,給出目標水量,可以執行一些操作,分別是倒空一個杯子,
倒滿一個杯子,和將一個杯子的水倒到另一箇中,問得到目標水量要進行至少多少次以及每次都是什麼並輸出,
FILL(1)表示倒滿1杯子,POUR(2,1)表示將2杯子裡的水倒進1杯子中,DROP(1)表示倒空1杯子。
如果做不到,輸出impossible。
這道題典型套BFS:給定初始狀態跟目標狀態,要求從初始狀態到目標狀態的最短路。
本體為廣度優先生成樹,每次對六種操作進行廣度搜尋,用二維陣列進行狀態是否出現過的標記,並記錄每次出現的節點的父節點,最後用遞迴進行輸出。AC程式碼:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stdlib.h>
using namespace std;
int A,B,C;
struct node{
int v1,v2;
int step;
int type; //操作類別:0代表倒完杯1,1代表倒完杯2,2代表裝滿杯1,3代表裝滿杯2,
//4代表杯1向杯2倒水,5代表杯2向杯1倒水
node *last; //指向它的上一個狀態
};
int vis[105][105];
void operate(int i,node *s,node *e){ //6種操作
e->type=i;
if(i==0){
e->v1=0;
e->v2=s->v2;
}
else if(i==1){
e->v2=0;
e->v1=s->v1;
}
else if(i==2){
e->v1=A;
e->v2=s->v2;
}
else if(i==3){
e->v2=B;
e->v1=s->v1;
}
else if(i==4){
if(s->v1>=(B-s->v2)){
e->v2=B;
e->v1=s->v1-(B-s->v2);
}
else{
e->v1=0;
e->v2=s->v2+s->v1;
}
}
else {
if(s->v2>=(A-s->v1)){
e->v1=A;
e->v2=s->v2-(A-s->v1);
}
else{
e->v2=0;
e->v1=s->v2+s->v1;
}
}
e->last=s;
e->step=s->step+1;
}
node* Bfs(){
int i;
memset(vis,0,sizeof(vis));
queue<node *>q;
vis[0][0]=1;
node *s;
s=(node *)malloc(sizeof(node));
s->v1=0;
s->v2=0;
s->type=-1;
s->step=0;
s->last=NULL;
q.push(s);
while(!q.empty()){
s=q.front();
q.pop();
if(s->v1==C||s->v2==C)
return s;
for(i=0;i<6;i++){
node *e;
e=(node *)malloc(sizeof(node));
operate(i,s,e);
if(vis[e->v1][e->v2])continue;
vis[e->v1][e->v2]=1;
q.push(e);
}
}
return NULL; //不能做到
}
void Output(node *t){ //遞迴地輸出倒水的步驟
if(t->last==NULL)return;
Output(t->last);
if(t->type==0)printf("DROP(1)\n");
else if(t->type==1)printf("DROP(2)\n");
else if(t->type==2)printf("FILL(1)\n");
else if(t->type==3)printf("FILL(2)\n");
else if(t->type==4)printf("POUR(1,2)\n");
else printf("POUR(2,1)\n");
}
int main()
{
while(scanf("%d %d %d",&A,&B,&C)!=EOF){
if(!Bfs())
{
printf("impossible\n");
continue;
}
printf("%d\n",Bfs()->step);
Output(Bfs());
}
return 0;
}