POJ 3414 Pots (BFS)

本文介绍使用广度优先搜索(BFS)算法解决水罐问题的方法,并详细解释了如何通过状态表示与转换来找到从初始状态到目标状态的最短路径。文章提供了完整的C++实现代码,展示了如何记录路径并逆向输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果用状态这个术语来表示的话,那么显然,两个杯子中水的情况对应了一个状态。  所以用BFS很容易求出最小值。   

该题的打印路径其实和紫书上第6张中迷宫问题用的方法是一样的,用一个父亲指针记录路劲个,这样就可以很方便的打印出路径。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<list>
#include<set>
#include<cmath>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int INF = 1e9;
const int maxn = 100 + 15;
int n,m,T,a,b,c,t,d[maxn][maxn];
char ans[maxn][maxn],table[20][maxn] = {"FILL(2)","FILL(1)","DROP(1)","DROP(2)","POUR(2,1)","POUR(1,2)"};
struct node{
    int a,b;
    char s[maxn];
    node(int a=0, int b=0): a(a),b(b) {}
    bool operator == (const node& rhs) const {
        return a == rhs.a && b == rhs.b;
    }
}path[maxn][maxn];
void print(node u) {
    int cnt = 0;
    while(d[u.a][u.b]>0) {
        memcpy(ans[cnt],u.s,sizeof(u.s));
        cnt++;
        u = path[u.a][u.b];
    }
    printf("%d\n",cnt);
    for(int i=cnt-1;i>=0;i--) {
        printf("%s\n",ans[i]);
    }
}
void bfs(node s) {
    queue<node> q; s.s[0] = 's'; s.s[1] = '\0';
    memset(d,-1,sizeof(d));
    d[s.a][s.b] = 0;
    q.push(s);
    while(!q.empty()) {
        node u = q.front(); q.pop();
        if(u.a == c || u.b == c) { print(u); return ; }
        node v = u;
        memcpy(v.s,table[0],sizeof(table[0]));
        v.b = b;
        if(d[v.a][v.b] == -1) {
            d[v.a][v.b] = d[u.a][u.b] + 1;
            path[v.a][v.b] = u;
            q.push(v);
        } v = u;
        memcpy(v.s,table[1],sizeof(table[1]));
        v.a = a;
        if(d[v.a][v.b] == -1) {
            d[v.a][v.b] = d[u.a][u.b] + 1;
            path[v.a][v.b] = u;
            q.push(v);
        } v = u;
        memcpy(v.s,table[2],sizeof(table[2]));
        v.a = 0;
        if(d[v.a][v.b] == -1) {
            d[v.a][v.b] = d[u.a][u.b] + 1;
            path[v.a][v.b] = u;
            q.push(v);
        } v = u;
        memcpy(v.s,table[3],sizeof(table[3]));
        v.b = 0;
        if(d[v.a][v.b] == -1) {
            d[v.a][v.b] = d[u.a][u.b] + 1;
            path[v.a][v.b] = u;
            q.push(v);
        } v = u;
        memcpy(v.s,table[4],sizeof(table[4]));
        if(v.a+v.b <= a) { v.a += v.b; v.b = 0; }
        else { v.b -= (a-v.a); v.a = a; }
        if(d[v.a][v.b] == -1) {
            d[v.a][v.b] = d[u.a][u.b] + 1;
            path[v.a][v.b] = u;
            q.push(v);
        } v = u;
        memcpy(v.s,table[5],sizeof(table[5]));
        if(v.a+v.b <= b) { v.b += v.a; v.a = 0; }
        else { v.a -= (b-v.b); v.b = b; }
        if(d[v.a][v.b] == -1) {
            d[v.a][v.b] = d[u.a][u.b] + 1;
            path[v.a][v.b] = u;
            q.push(v);
        }
    }
    printf("impossible\n");
    return ;
}
int main() {
    scanf("%d%d%d",&a,&b,&c);
        if(a < c && b < c) printf("impossible\n");
        else bfs(node(0,0));
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值