Pots:倒水问题

问题描述:
给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作
FILL(i) 将第i个容器从水龙头里装满(1 ≤ i ≤ 2);
DROP(i) 将第i个容器抽干
POUR(i,j) 将第i个容器里的水倒入第j个容器(这次操作结束后产生两种结果,一是第j个容器倒满并且第i个容器依旧有剩余,二是第i个容器里的水全部倒入j中,第i个容器为空)
现在要求你写一个程序,来找出能使其中任何一个容器里的水恰好有C升,找出最少操作数并给出操作过程
Input
有且只有一行,包含3个数A,B,C(1<=A,B<=100,C<=max(A,B))

Output
第一行包含一个数表示最小操作数K
随后K行每行给出一次具体操作,如果有多种答案符合最小操作数,输出他们中的任意一种操作过程,如果你不能使两个容器中的任意一个满足恰好C升的话,输出“impossible”
题意:
给你a,b两个容器的容量,六种操作方法,问最少多少次可以使其中一个容器里的水达到体积c,如果不能的话则输出impossible。
思路:
对6种情况进行bfs,难点怎样记录最优情况的倒水过程,用一个三维数组op[i][j][k],表示在a为i升,b为j升时,进行了k次操作。
代码加注释理解:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stdio.h>
using namespace std;

const int Maxn=110;
struct node {
    int x,y;
} f1,f2;
int vis[Maxn][Maxn];	//步数和标记
int op[Maxn][Maxn][Maxn];	//记录过程
int a,b,c;

void Operator(int i)	//打印过程,与下面的bfs要一一对应
{
    switch(i) 
	{
    case 0:
        printf("FILL(1)\n");
        break;
    case 1:
        printf("FILL(2)\n");
        break;
    case 2:
        printf("POUR(1,2)\n");
        break;
    case 3:
        printf("POUR(2,1)\n");
        break;
    case 4:
        printf("DROP(1)\n");
        break;
    case 5:
        printf("DROP(2)\n");
        break;
    }
}
void bfs()
{
    int i,j;
    queue<node >q;
    memset(vis,-1,sizeof(vis));
    vis[0][0]=0;
    f1.x=0;
    f1.y=0;
    q.push(f1);
    while(!q.empty()) 
	{
        f1=q.front();
        q.pop();
        if(f1.x==c||f1.y==c) //遇到符合条件的就直接打印
		{
            printf("%d\n",vis[f1.x][f1.y]);
            for(i=1; i<=vis[f1.x][f1.y]; i++) 
			{
                Operator(op[f1.x][f1.y][i]);
            }
            return;
        }
        for(i=0; i<6; i++) //对6种情况进行遍历
		{
            if(i==0) 
			{
                f2.x=a;
                f2.y=f1.y;
            }
            if(i==1) 
			{
                f2.x=f1.x;
                f2.y=b;
            }
            if(i==2) 
			{
                f2.y = f1.x + f1.y;
                if(f2.y>=b) 
				{
                    f2.x=f2.y-b;
                    f2.y=b;

                } else
                    f2.x=0;
            }
            if(i==3) 
			{
                f2.x=f1.y+f1.x;
                if(f2.x>=a) 
				{
                    f2.y=f2.x-a;
                    f2.x=a;
                } 
				else
                    f2.y=0;
            }
            if(i==4) 
			{
                f2.x=0;
                f2.y=f1.y;
            }
            if (i==5) 
			{
                f2.x=f1.x;
                f2.y=0;
            }
            if(vis[f2.x][f2.y]==-1) //对于相同的情况就可以省略,新的就可以记录与进队列
			{
                vis[f2.x][f2.y]=vis[f1.x][f1.y]+1;	//步数加一
                for(j=1; j<=vis[f1.x][f1.y]; j++)	//对前一种情况的过程,进行拷贝
                    op[f2.x][f2.y][j]=op[f1.x][f1.y][j];
                op[f2.x][f2.y][vis[f1.x][f1.y]+1]=i;	//新加入的情况加入原过程
                q.push(f2);
            }
        }
    }
    puts("impossible");
}
int main()
{
    while(~scanf("%d%d%d",&a,&b,&c)) 
    {
        bfs();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46687179/article/details/105899976