poj 3414

大致题意:
两个杯子,每次可进行6种不同的操作
FULL 将一个杯子加满水
DROP 将一个杯子内的水全部倒掉
POUR 将一个杯子的水倒入另一个杯子(中间不浪费水,一个杯子满了另一个杯子就停止注水。。。)

要求当任意一个杯子的水量为c时,输出操作的次数以及过程

这道题做的我很头大。。。因为我第一次遇到要求保存路径的bfs搜索题
通过一些大佬的代码我大概了解了应该怎么存。。。

首先把操作给编号
string path[]=
{
“FILL(1)”,
“FILL(2)”,
“DROP(1)”,
“DROP(2)”,
“POUR(1,2)”,
“POUR(2,1)”,
};

这样FILL(1)对应的编号就是0,依次类推。。。
在结构体中使用path进行保存
struct node
{
int a,b,level;
int path[105];
int plen;
};
path里的每一个数字就代表曾经进行过的操作。。。

之后在每次确定一个新的状态后,就将path中的某一个数改变为当前的操作编号,使用plen进行当前path[]序号的保存
plen++ 在出现一个新的状态时去控制

最后输出答案时遍历一边结构体中的path即可,(我没看懂的地方是为什么好多人都是用char来保存编号,并在输出时强制转换类型为int。。。)

之后要注意的细节就是要有一个二维数组去保存状态,重复出现过的状态直接pass掉
在POUR操作时要注意考虑清楚两种不同的情况

#include <cstdio>
#include <queue>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

int a,b,c,i,j;
int vis[105][105];

string path[]=
{
    "FILL(1)",
    "FILL(2)",
    "DROP(1)",
    "DROP(2)",
    "POUR(1,2)",
    "POUR(2,1)",
};

struct node
{
    int a,b,level;
    int path[105];
    int plen;
};


void bfs(int a,int b,int c)
{
    node s,t;
    queue<node>q;
    s.a=0;
    s.b=0;
    s.plen=0;
    s.level=0;
    vis[0][0]=1;

    q.push(s);

    while(!q.empty())
    {
        s=q.front();
        q.pop();

        if(s.a==c||s.b==c)
        {
            cout<<s.level<<endl;
            for(i=0;i<s.plen;i++)
            {
                cout<<path[s.path[i]]<<endl;
            }
            return;
        }

        t=s;
        t.plen++;
        t.level++;

        //FILL(1)
        if(t.a<a)
        {
            t.a=a;
            t.b=s.b;

            if(vis[t.a][t.b]==0)
            {
                vis[t.a][t.b]=1;
                t.path[s.plen]=0;
                q.push(t);
            }
        }

        //FILLL(2)
        if(t.b<b)
        {
            t.a=s.a;
            t.b=b;

            if(vis[t.a][t.b]==0)
            {
                vis[t.a][t.b]=1;
                t.path[s.plen]=1;
                q.push(t);
            }
        }

        //DROP(1)
        if(t.a>0)
        {
            t.a=0;
            t.b=s.b;

            if(vis[t.a][t.b]==0)
            {
                vis[t.a][t.b]=1;
                t.path[s.plen]=2;
                q.push(t);
            }
        }


        //DROP(2)
        if(t.b>0)
        {
            t.a=s.a;
            t.b=0;
            if(vis[t.a][t.b]==0)
            {
                vis[t.a][t.b]=1;
                t.path[s.plen]=3;
                q.push(t);
            }
        }

        //POUR(1,2)
        if(s.a>0&&s.b<b)
        {
            if(s.a>=b-s.b)
            {
                t.a=s.a-(b-s.b);
                t.b=b;
            }
            else
            {
                t.a=0;
                t.b=s.b+s.a;
            }

            if(vis[t.a][t.b]==0)
            {
                vis[t.a][t.b]=1;
                t.path[s.plen]=4;
                q.push(t);
            }
        }

        //POUR(2,1)
        if(s.b>0&&s.a<a)
        {
            if(s.b>=a-s.a)
            {
                t.a=a;
                t.b=s.b-(a-s.a);
            }
            else
            {
                t.a=s.a+s.b;;
                t.b=0;
            }
            if(vis[t.a][t.b]==0)
            {
                vis[t.a][t.b]=1;
                t.path[s.plen]=5;
                q.push(t);
            }
        }
    }

    printf("impossible\n");
}

int main()
{
    cin>>a>>b>>c;

    bfs(a,b,c);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值