POJ.3414 Pots (BFS)

POJ.3414 Pots (BFS)

题意分析

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

BFS时其实有6种操作,因为要考虑1向2中倒水是会不会将2倒满,2向1倒水的时候同理。

对于输出路径,可以用一个二维数组来保存状态,同时保存他的前驱节点。
最后输出的时候,需要用到一下栈来逆置。

代码总览

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#define nmax 105
using namespace std;
typedef struct{
    int Anet;
    int Bnet;
    int time;
}pot;
int ansTimes,ansX,ansY;
typedef struct{
    int type;
    int X,Y;
    bool isvisit;
}mes;
mes visit[nmax][nmax];
int A,B,C;
void bfs()
{
    queue<pot> q;
    while(!q.empty()) q.pop();
    pot temp = {0,0,0},head;
    q.push(temp);
    visit[temp.Anet][temp.Bnet].isvisit = true;
    visit[temp.Anet][temp.Bnet].type = -1;
    while(!q.empty()){
        head = q.front(); q.pop();
        if(head.Anet == C || head.Bnet == C){
            ansTimes = head.time;
            ansX = head.Anet;
            ansY = head.Bnet;
            return;
        }
        for(int i = 1;i<=6;++i){
            temp = head;
            temp.time = head.time+1;
            if(i == 1){
                temp.Anet = A;
            }else if(i == 2){
                temp.Bnet = B;
            }else if(i == 3){
                temp.Anet = 0;
            }else if(i == 4){
                temp.Bnet = 0;
            }else if(i == 5){
                int k1 = temp.Anet, k2 = temp.Bnet;
                if(k1+k2 < A){
                    temp.Anet = k1+k2;
                    temp.Bnet = 0;
                }else{
                    temp.Anet = A;
                    temp.Bnet = k1+k2 - A;
                }
            }else if(i == 6){
                int k1 = temp.Anet, k2 = temp.Bnet;
                if(k1+k2 < B){
                    temp.Bnet = k1+k2;
                    temp.Anet = 0;
                }else{
                    temp.Bnet = B;
                    temp.Anet = k1+k2 - B;
                }
            }
            //printf("%d %d %d\n",temp.Anet,temp.Bnet,i);
            if(visit[temp.Anet][temp.Bnet].isvisit == false){
                //printf("OK FOR %d %d %d\n",temp.Anet,temp.Bnet,i);
                q.push(temp);
                //printf("%d\n",q.size());
                visit[temp.Anet][temp.Bnet].isvisit = true;
                visit[temp.Anet][temp.Bnet].type = i;
                visit[temp.Anet][temp.Bnet].X = head.Anet;
                visit[temp.Anet][temp.Bnet].Y = head.Bnet;
            }
        }
    }
    ansTimes = -1;
}
void output(int x, int y)
{
    vector<string> v; v.clear();
    int a = x,b = y;
    while(visit[x][y].type != -1){
        if(visit[x][y].type == 1){
            v.push_back("FILL(1)");
        }else if(visit[x][y].type == 2){
            v.push_back("FILL(2)");
        }else if(visit[x][y].type == 3){
            v.push_back("DROP(1)");
        }else if(visit[x][y].type == 4){
            v.push_back("DROP(2)");
        }else if(visit[x][y].type == 5){
            v.push_back("POUR(2,1)");
        }else{
            v.push_back("POUR(1,2)");
        }
        a = visit[x][y].X;
        b = visit[x][y].Y;
        x = a;
        y = b;
    }
    for(int i = v.size()-1;i>=0;--i){
        printf("%s\n",v[i].c_str());
    }
}
int main()
{
    while(scanf("%d %d %d",&A,&B,&C)!= EOF){
        memset(visit,0,sizeof(visit));
        bfs();
        if(ansTimes == -1){
            printf("impossible\n");
        }else{
            printf("%d\n",ansTimes);
            output(ansX,ansY);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值