POJ 3414 Pots(深搜并打印路径)
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
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).
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.
Input
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
Output
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.
Sample Input
3 5 4
Sample Output
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
解题思路:
1.两遍dfs,第一遍找到最小的倒水次数,第二遍打印路径
2.倒水问题:模拟倒水的6种情况
#include<iostream>//代码稍微有点长,但是思路很简单
#include<cstdlib>
#include<cstring>
#include<stack>
#define INF 0x7fffffff
using namespace std;
typedef struct node{
int x;//操作x==1代表操作FILL,x==2代表操作DROP
int y;//代表操作的参数如x==1,y==2则代表FILL(2)
int z;
}Node;
Node temp;
stack<Node>s;//利用栈记录路径
int book[110][110];//标记数组
int flag=0;
int mins=INF;
int a,b,tol;
void dfs(int x,int y,int sum,int f,int fx,int fy) {
//参数x,y记录第1个和第2个水杯的水量,sum代表操作次数,
//f代表当前操作,fx,fy是操作的两个参数
if(x==tol||y==tol) {//当符合情况时更新最小值
if(sum<mins){
mins=sum;
}
return;
}
int xx,yy,ff,ffx,ffy;
if(x!=0) {//第一种情况,当第一个水杯有水时全部倒出DROP(1)
xx=0;
yy=y;
ff=2;//记录是第几个操作
ffx=1;//记录操作的第一个参数
ffy=0;//记录操作的第二个参数(只有在POUR操作下才有)
if(book[xx][yy]==0){//没出现过此种状态
book[xx][yy]=1;
dfs(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
}
}
if(y!=0) {//第2种情况,当第2个水杯有水时全部倒出DROP(2)
xx=x;
yy=0;
ff=2;
ffx=2;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
dfs(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
}
}
if(x!=a) {第3种情况,当第1个水杯没有装满时倒满水FILL(1)
xx=a;
yy=y;
ff=1;
ffx=1;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
dfs(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
}
}
if(y!=b) {//第4种情况,当第2个水杯没有装满时倒满水FILL(2)
xx=x;
yy=b;
ff=1;
ffx=2;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
dfs(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
}
}
if(x!=a&&y!=0) {//第5种情况,当第1个水杯不满,第2个水杯有水时,
//将第二个水杯的水倒入第一个水杯POUR(2,1)
xx=min(x+y,a);
yy=y-(xx-x);
ff=3;
ffx=2;
ffy=1;
if(book[xx][yy]==0){
book[xx][yy]=1;
dfs(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
}
}
if(x!=0&&y!=b) {
第6种情况,当第2个水杯不满,第1个水杯有水时,
//将第1个水杯的水倒入第2个水杯POUR(1,2)
yy=min(x+y,b);
xx=x-(yy-y);
ff=3;
ffx=1;
ffy=2;
if(book[xx][yy]==0){
book[xx][yy]=1;
dfs(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
}
}
return;
}
void prints(int f,int fx,int fy){//打印一步的操作
if(f==1){
cout<<"FILL("<<fx<<")"<<endl;
}
else if(f==2){
cout<<"DROP("<<fx<<")"<<endl;
}
else if(f==3){
cout<<"POUR("<<fx<<","<<fy<<")"<<endl;
}
}
void print(int x,int y,int sum,int f,int fx,int fy) {//寻找路径并记录路径
if(x==tol||y==tol) {
if(sum==mins){//当达到最小值时记录此路径
flag=1;
}
return;
}
int xx,yy,ff,ffx,ffy;
if(x!=0) {//和上边的dfs思路一样,只不过多了一个判断
xx=0;
yy=y;
ff=2;
ffx=1;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
print(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
if(flag==1){//多个这个判断
temp.x=ff;
temp.y=ffx;
temp.z=ffy;
s.push(temp);
return;
}
}
}
if(y!=0) {
xx=x;
yy=0;
ff=2;
ffx=2;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
print(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
if(flag==1){
temp.x=ff;
temp.y=ffx;
temp.z=ffy;
s.push(temp);
return;
}
}
}
if(x!=a) {
xx=a;
yy=y;
ff=1;
ffx=1;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
print(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
if(flag==1){
temp.x=ff;
temp.y=ffx;
temp.z=ffy;
s.push(temp);
return;
}
}
}
if(y!=b) {
xx=x;
yy=b;
ff=1;
ffx=2;
ffy=0;
if(book[xx][yy]==0){
book[xx][yy]=1;
print(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
if(flag==1){
temp.x=ff;
temp.y=ffx;
temp.z=ffy;
s.push(temp);
return;
}
}
}
if(x!=a&&y!=0) {
xx=min(x+y,a);
yy=y-(xx-x);
ff=3;
ffx=2;
ffy=1;
if(book[xx][yy]==0){
book[xx][yy]=1;
print(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
if(flag==1){
temp.x=ff;
temp.y=ffx;
temp.z=ffy;
s.push(temp);
return;
}
}
}
if(x!=0&&y!=b) {
yy=min(x+y,b);
xx=x-(yy-y);
ff=3;
ffx=1;
ffy=2;
if(book[xx][yy]==0){
book[xx][yy]=1;
print(xx,yy,sum+1,ff,ffx,ffy);
book[xx][yy]=0;
if(flag==1){
temp.x=ff;
temp.y=ffx;
temp.z=ffy;
s.push(temp);
return;
}
}
}
return;
}
int main() {
cin>>a>>b>>tol;
memset(book,0,sizeof(book));
book[0][0]=1;
dfs(0,0,0,0,0,0);//寻找最少倒换几次
if(mins!=INF){
cout<<mins<<endl;
memset(book,0,sizeof(book));
book[0][0]=1;
print(0,0,0,0,0,0);//寻找路径
while(!s.empty()){//输出路径
temp=s.top();
s.pop();
prints(temp.x,temp.y,temp.z);
}
}
else{
cout<<"impossible"<<endl;
}
return 0;
}