Pots POJ - 3414
给你两个罐子,
分别有A升和B升的体积
这里开始的时候A和B的杯子都是没有水的
。可以执行以下操作:
1,FILL(i)从水龙头填充锅i (1 ≤ i ≤ 2);
2,DROP(i) 将锅i排空至排水管;
3,POUR(i,j) 从锅i倒入锅j;在此操作之后,要么锅j已满(锅i 中可能还有一些水),要么锅i是空的(并且其所有内容都已移到锅j 中)。
编写一个程序,找出这些操作的最短可能序列,以便在其中一个锅中产生恰好C升的水。
输入
第一行也是唯一一行是数字A、B和C。这些都是 1 到 100 范围内的整数,并且C ≤max( A , B )。
输出
输出的第一行必须包含操作序列K的长度。以下K行必须每行描述一个操作。如果有几个最小长度的序列,输出其中的任何一个。如果无法达到预期的结果,文件的第一行也是唯一的一行必须包含单词“impossible”。
Inpput
3 5 4
Sample Output
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
思路:看到题目的最短操作用bfs模拟;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int vist[110][110];//保存的是A和B的量是否标记过
int A,B,C,flag,o;
string work[10]= {"","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};//走相应的操作
struct node {
int x;
int y;
int step;//几步
string s;//对应work的数字
};
queue<node> q;
void bfs() {
q.push({0,0,0,"0"});
vist[0][0]=1;
while(!q.empty()) {
node H=q.front();
q.pop();
if(H.x==C||H.y==C){// A或B有其中一个产生C量的水,则立刻输出步数
cout<<H.step<<endl;
for(int i=1;i<H.s.size();i++){//输出对应的步骤
cout<<work[H.s[i]-'0']<<endl;
}
flag=1;//标记成功
return ;
}
//下面对应着6个操作,每个都来,操作的时候考虑实际状况,比如是否满了;或者是否清空没有了
if(H.x<A&&(!vist[A][H.y])) { //FILL(1)
vist[A][H.y]=1;
q.push({A,H.y,H.step+1,H.s+"1"});
}
if(H.y<B&&(!vist[H.x][B])) { //FILL(2)
vist[H.x][B]=1;
q.push({H.x,B,H.step+1,H.s+"2"});
}
if(H.x>0&&(!vist[0][H.y])) { //DROP(1)
vist[0][H.y]=1;
q.push({0,H.y,H.step+1,H.s+"3"});
}
if(H.y>0&&(!vist[H.x][0])) { //DROP(2)
vist[H.x][0]=1;
q.push({H.x,0,H.step+1,H.s+"4"});
}
if(H.x!=0&&H.y<B) { //POUR(1,2)
int nx,ny;
if(H.x+H.y<=B) {
ny=H.x+H.y;
nx=0;
} else {
nx=H.x+H.y-B;
ny=B;
}
if(!vist[nx][ny]) {
vist[nx][ny]=1;
q.push({nx,ny,H.step+1,H.s+"5"});
}
}
if(H.y!=0&&H.x<A){ //POUR(2,1)
int nx,ny;
if(H.x+H.y<=A){
nx=H.x+H.y;
ny=0;
}
else{
nx=A;
ny=H.x+H.y-A;
}
if(!vist[nx][ny]){
vist[nx][ny]=1;
q.push({nx,ny,H.step+1,H.s+"6"});
}
}
}
}
int main() {
while(~scanf("%d%d%d",&A,&B,&C)) {
flag=0;
bfs();
if(!flag){
printf("impossible\n");//没有则输出 impossible
}
}
}