【BFS + 保存操作】POJ 3414 Pots

21 篇文章 0 订阅
15 篇文章 0 订阅

Problem Description

给你三个数据,分别表示两个杯子的体积,和要你装出来的体积,两个杯子可以互相倒,也可以倒掉水,也可以装满水。要你输出最少的操作步骤,包括如何操作的。

代码:以前在自家OJ做过一样的题,但是那个题,不需要保存操作。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<string>
using namespace std;
struct node
{
    int lt, rt;
    char s[15];
};
int a, b, c;
int vis[150][150];
node Pre[150][150];//用来保存路径
queue<node> q;
vector<string> p;//用来保存答案操作
void bfs()
{
    q.push((node){0,0});
    node t; int x, y, i;
    while(!q.empty())
    {
        t = q.front();
        q.pop();
        if(t.lt == c || t.rt == c)//如果有那个杯子容量达到要求
        {
            printf("%d\n", vis[t.lt][t.rt] - 1);//输出操作次数
            x = t.lt, y = t.rt;
            while(x || y)//最初始状态退出循环
            {
                t.lt = x, t.rt = y;
                p.push_back(Pre[t.lt][t.rt].s);//记录上一点的操作
                x = Pre[t.lt][t.rt].lt, y = Pre[t.lt][t.rt].rt;
            }
            for(i = p.size() - 1; i >= 0; i--)//倒着输出
            {
                printf("%s\n", p[i].c_str());
            }
            return;
        }
        for(i = 0; i < 6; i++)//有六种情况
        {
            if(i == 0 && t.lt != a)//装满a
            {
                x = a; y = t.rt;
                if(!vis[x][y])
                {
                    vis[x][y] = vis[t.lt][t.rt] + 1;//操作步骤+1
                    Pre[x][y] = (node){t.lt, t.rt, "FILL(1)"};//存入上一个点的下标,和操作成这点的步骤
                    q.push((node){x, y});
                }
            }
            if(i == 1 && t.rt != b)//装满b
            {
                x = t.lt; y = b;
                if(!vis[x][y])
                {
                    vis[x][y] = vis[t.lt][t.rt] + 1;
                    Pre[x][y] = (node){t.lt, t.rt, "FILL(2)"};
                    q.push((node){x, y});
                }
            }
            if(i == 2)//a倒入b
            {
                if(t.lt + t.rt >= b)//倒满b
                {
                    x = t.lt + t.rt - b; y = b;
                }
                else//倒不满b
                {
                    x = 0; y = t.lt + t.rt;
                }
                if(!vis[x][y])
                {
                    vis[x][y] = vis[t.lt][t.rt] + 1;
                    Pre[x][y] = (node){t.lt, t.rt, "POUR(1,2)"};
                    q.push((node){x, y});
                }
            }
            if(i == 3)//b倒入a
            {
                if(t.lt + t.rt >= a)//倒满a
                {
                    x = a; y = t.lt + t.rt - a;
                }
                else//不能倒满a
                {
                    x = t.lt + t.rt; y = 0;
                }
                if(!vis[x][y])
                {
                    vis[x][y] = vis[t.lt][t.rt] + 1;
                    Pre[x][y] = (node){t.lt, t.rt, "POUR(2,1)"};
                    q.push((node){x, y});
                }
            }
            if(i == 4 && x != 0)//倒掉a
            {
                x = 0; y = t.rt;
                if(!vis[x][y])
                {
                    vis[x][y] = vis[t.lt][t.rt] + 1;
                    Pre[x][y] = (node){t.lt, t.rt, "DROP(1)"};
                    q.push((node){x, y});
                }
            }
            if(i == 5 && y != 0)//倒掉b
            {
                x = t.lt; y = 0;
                if(!vis[x][y])
                {
                    vis[x][y] = vis[t.lt][t.rt] + 1;
                    Pre[x][y] = (node){t.lt, t.rt, "DROP(2)"};
                    q.push((node){x, y});
                }
            }
        }
    }
    printf("impossible\n");
}
int main()
{
    while(~scanf("%d %d %d", &a, &b, &c))
    {
        memset(vis, 0, sizeof(vis));
        while(!q.empty()) q.pop();//初始化队列
        vis[0][0] = 1;//最开始的状态标记一下
        bfs();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值