[kuangbin带你飞]专题一 简单搜索 Pots : BFS

题意:

有两个被子,容量分别是A和B,想得到目标容量C(A、B中任意一个容量是C就行)。

有3个操作:

 1. FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
 2. DROP(i) empty the pot i to the drain;
 3. POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).

输出最少步骤,并且回溯操作过程。


题解:

这题是经典的BFS题,难点就是 “回溯操作的过程”。

我是这样做的:我把所有的状态节点从queue pop出来之前,都加到vector里面,保存起来!然后节点cur中有个变量 pre,这个cur.pre表示的是 前一个操作的节点在vector中的下标。其中,节点最多有 100*100=10000个。而状态标记数组可以用f[105][105]来实现。

节点结构:

typedef struct Node{

    int x,y,stp,opt,pre;

}Node;


代码:

1A。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

int f[105][105];
typedef struct Node{
    int x,y,stp,opt,pre;

}Node;

char s[7][10]={
    "","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"
};

Node st,en;
int A,B,C,ans;
vector<Node >v;

void operate(int indx,Node *nw){
    int tot=nw->x+nw->y;
    
    if(indx==1)//fill(1)
        nw->x=A;

    if(indx==2)//fill(2)
        nw->y=B;
    
    if(indx==3)//drop(1)
        nw->x=0;
    
    if(indx==4)//drop(2)
        nw->y=0;
    
    if(indx==5){//pour(1,2)
        if(tot>=B){
            nw->x=tot-B;
            nw->y=B;
        }else{
            nw->x=0;
            nw->y=tot;
        }
    }
    
    if(indx==6){//pour(2,1)
        if(tot>=A){
            nw->x=A;
            nw->y=tot-A;
        }else{
            nw->x=tot;
            nw->y=0;
        }
    }
    
}

void print_ans(Node en){
    if(en.pre==-1){
        //printf("%d %s\n",en.stp,s[en.opt]);
        return;
    }
    
    Node p= v[en.pre];
    print_ans(p);
    printf("%s\n",s[en.opt]);
}


int main(int argc, const char * argv[]) {
    

    
    while(~scanf("%d%d%d",&A,&B,&C)){
    
        st.x=0; st.y=0;
        st.opt=-1; st.stp=0;
        st.pre=-1;
        memset(f,0,sizeof(f));
        f[0][0]=1;
        
        queue<Node >Q;
        v.clear();
        Q.push(st);
        ans=-1;
        
        while(!Q.empty()){
            Node cur,nw;
            cur=Q.front();
            
            //节点存档
            v.push_back(cur);
            
            if(cur.x==C || cur.y==C) {
                ans=cur.stp;
                en=cur;
                break;
            }
            
            for(int i=1;i<=6;i++)
            {
                nw=cur;
                operate(i,&nw);
                if(!f[nw.x][nw.y]){
                    
                    f[nw.x][nw.y]=1;
                    nw.stp=cur.stp+1;
                    nw.opt=i;
                    nw.pre=(int)v.size()-1;
                    Q.push(nw);
                }
            }
            
            Q.pop();
        }
    
        
        if(ans!=-1) {
            printf("%d\n",ans);
            print_ans(en);
        }
        else puts("impossible");
    
        
        
    }
    
    
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值