Pots POJ - 3414

题目:
小明给你两个容器,分别能装下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”

Sample
Input

3 5 4
Sample Output
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)

思路比较容易想到;就是用bfs有6个方向,具体细节看代码

ac代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<string>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;

int A,B,C;
string print[6]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
typedef struct
{
    int A,B;
    int pre;
    int op; //记录该点经行的操作
}status; 
status a[10005];//记录路径
int cnt=1;     //索引作用
int len;

status bfs()
{
    status first;
    first.A = 0;
    first.B = 0;
    first.pre=-1;   //标记头节点 
    a[0] =  first;
    for(int k=0;;k++)
    {
        if(k>=cnt)  break;	//说明无新增
        for(int i=0;i<6;i++)
        {
            status New;
            New = a[k];
            New.pre = k;
            New.op = i;
            if(i==0)
            {
                if(New.A==A)    continue;
                //加continue的意思是表明该点已访问,不必在进行后续记录操作
                New.A = A;
            }
            if(i==1)
            {
                if(New.B==B)    continue;
                New.B = B;
            }
            if(i==2)
            {
                if(New.A==0)    continue;
                New.A = 0;
            }
            if(i==3)
            {
                if(New.B==0)    continue;
                New.B = 0;
            }
            if(i==4)
            {
                int pour = min(New.A,B-New.B);
                if(pour==0) continue;
                New.A -=pour;
                New.B +=pour; 
            }
            if(i==5)
            {
                int pour = min(New.B,A-New.A);
                if(pour==0) continue;
                New.A +=pour;
                New.B -=pour; 
            }
            if(New.A==C||New.B==C)
            {
                return New;
            }

	   //一下为记录路径的操作
            bool flag = false;
            for(int j=0;j<cnt;j++)
            {
                if(a[j].A==New.A&&a[j].B==New.B)
                {
                    flag = true;
                    break;
                }
            }
            if(!flag)   a[cnt++]=New;
        }
    }
    status loser;
    loser.pre =-2;      //标记没有找到 
    return loser;
}
void coutt(status New)
{
    if(New.pre==-2)
    {
        cout<<"impossible\n"<<endl;
        return ;
    }
    if(New.pre == -1)
    //找到头节点返回
    {
        cout<<len<<endl;
        return;
    }
    else
    {
        len++;
        coutt(a[New.pre]);
        cout<<print[New.op]<<endl;
    }
    return;
}
int main()
{
    scanf("%d%d%d",&A,&B,&C);
    coutt(bfs());
    return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值