POJ-3414

这只是一道记录状态的步骤多一点的bfs罢了。

每一步都最多有六种下一步:

1.清空A,  2.清空B  3.装满A  4.装满B  5.将A中液体倒入B  6.将B中液体倒入A;

//step[][]数组用来记录步数

 

//Node gogo[][]用来记载每一步具体是干什么的;

比如:父状态是:      a: 0 b: 0

将设子状态是装满B则子状态为na: 0 nb: B nc: 4(对应状态编号)

那么gogo[na][nb]=Node(a,a,nc);

也就是每一次这一步的gogo都存了上一步的状态,以及到达这一步需要的操作;

 

可以根据下标关系找到这一状态的上一次状态,于是想到可以遍历到最后合适的结果时,将到这一步之前的状态压入栈,再遍历一次即是答案;

我给出题目的样例的bfs过程,还有注释的地方可以知道遍历完毕后所有的状态;

每一步都是当前状态的AB杯的液体量,以及操作的由来:(我旋转不了图像。。。)

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const double epos=1e-8;
const int maxn=109;

struct Node{
    int a,b;
    int c;
}tan1,in;

ostream& operator <<(ostream& os,const Node& x){
        os <<x.a<<"+"<<x.b<<"+"<<x.c<<"  ";
        return os;
    }

int A,B,C;
int step[maxn][maxn];
int flag[maxn][maxn];
Node gogo[maxn][maxn];

/*
1 FILL(1)
2 FILL(2)
3 DROP(1)
4 DROP(2)
5 POUR(1,2)
6 POUR(2,1)
*/

char s[8][12]={"000","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};

void bfs(){
    memset(flag,0,sizeof(flag));
    memset(step,0,sizeof(step));
    memset(gogo,0,sizeof(gogo));
    queue<Node>q;
    in.a=in.b=in.c=0;
    flag[0][0]=1;
    q.push(in);
    while(!q.empty()){
        tan1=q.front();
        q.pop();
        if(tan1.a==C||tan1.b==C){
            printf("%d\n",step[tan1.a][tan1.b]);
//            for(int i=0;i<=A;i++){
//                for(int j=0;j<=B;j++)
//                    cout<<gogo[i][j];
//                cout<<endl;
//
//            }
            stack<int>ss;
            int i=tan1.a;
            int j=tan1.b;
            while(1){
                if(i==0&&j==0&&gogo[i][j].c==0)
                    break;
                ss.push(gogo[i][j].c);
                int t1=gogo[i][j].a;
                int t2=gogo[i][j].b;
                i=t1,j=t2;
            }
            while(!ss.empty()){
                printf("%s\n",s[ss.top()]);
                ss.pop();
            }
            return ;
        }

        //FILL(1);
        if(tan1.a<A){
            in.a=A;
            in.b=tan1.b;
            in.c=1;
            if(flag[in.a][in.b]==0){
                flag[in.a][in.b]=1;
                Node go;
                go.a=tan1.a;
                go.b=tan1.b;
                go.c=1;
                q.push(in);
                step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                gogo[in.a][in.b]=go;
            }
        }

        //FILL(2);
        if(tan1.b<B){
            in.a=tan1.a;
            in.b=B;
            in.c=2;
            if(flag[in.a][in.b]==0){
                flag[in.a][in.b]=1;
                Node go;
                go.a=tan1.a;
                go.b=tan1.b;
                go.c=2;
                q.push(in);
                step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                gogo[in.a][in.b]=go;
            }
        }

        //DROP(1);
        if(tan1.a>0){
            in.a=0;
            in.b=tan1.b;
            in.c=3;
            if(flag[in.a][in.b]==0){
                flag[in.a][in.b]=1;
                Node go;
                go.a=tan1.a;
                go.b=tan1.b;
                go.c=3;
                q.push(in);
                step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                gogo[in.a][in.b]=go;
            }
        }

        //DROP(2);
        if(tan1.b>0){
            in.a=tan1.a;
            in.b=0;
            in.c=4;
            if(flag[in.a][in.b]==0){
                flag[in.a][in.b]=1;
                Node go;
                go.a=tan1.a;
                go.b=tan1.b;
                go.c=4;
                q.push(in);
                step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                gogo[in.a][in.b]=go;
            }
        }

        //POUR(1,2);
        if(tan1.a>0&&tan1.b<B){
            if(tan1.a+tan1.b<B){
                in.b=tan1.a+tan1.b;
                in.a=0;
                in.c=5;
                if(flag[in.a][in.b]==0){
                    flag[in.a][in.b]=1;
                    Node go;
                    go.a=tan1.a;
                    go.b=tan1.b;
                    go.c=5;
                    q.push(in);
                    step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                    gogo[in.a][in.b]=go;
                }
            }
            else{
                in.b=B;
                in.a=tan1.a-B+tan1.b;
                in.c=5;
                if(flag[in.a][in.b]==0){
                    flag[in.a][in.b]=1;
                    Node go;
                    go.a=tan1.a;
                    go.b=tan1.b;
                    go.c=5;
                    q.push(in);
                    step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                    gogo[in.a][in.b]=go;
                }
            }
        }

        //POUR(2,1);
        if(tan1.b>0&&tan1.a<A){
            if(tan1.a+tan1.b<A){
                in.b=0;
                in.a=tan1.a+tan1.b;
                in.c=6;
                if(flag[in.a][in.b]==0){
                    flag[in.a][in.b]=1;
                    Node go;
                    go.a=tan1.a;
                    go.b=tan1.b;
                    go.c=6;
                    q.push(in);
                    step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                    gogo[in.a][in.b]=go;
                }

            }
            else{
                in.a=A;
                in.b=tan1.b-A+tan1.a;
                in.c=6;
                if(flag[in.a][in.b]==0){
                    flag[in.a][in.b]=1;
                    Node go;
                    go.a=tan1.a;
                    go.b=tan1.b;
                    go.c=6;
                    q.push(in);
                    step[in.a][in.b]=step[tan1.a][tan1.b]+1;
                    gogo[in.a][in.b]=go;
                }
            }
        }
    }
    printf("impossible\n");
    return ;
}


int main(){
    scanf("%d%d%d",&A,&B,&C);
    bfs();
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值