【kuangbin】简单搜索 - 8.罐子【BFS】

Date:2022.02.06
题意:
给你两个罐子,容积分别为 A 升和 B 升。
现在,你可以进行如下三种操作:
1.FILL(i),将罐子 i(1≤i≤2)灌满水。
2.DROP(i),将罐子 i(1≤i≤2)清空。
3.POUR(i,j),将罐子 i 中的水倒向罐子 j,直到罐子 i 空了或罐子 j 满了为止。
请问,至少多少次操作后,可以使得其中一个罐子里恰好有 C 升水。
输入格式
共一行,三个整数 A,B,C。
输出格式
如果无解,则输出一行 impossible 即可。
否则,第一行输出一个整数,表示最少操作次数。
随后按顺序每行输出一个操作指令,格式参考题面。
数据范围
1≤A,B,C≤100,
C≤max(A,B)。
输入样例:
3 5 4
输出样例:
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)

思路:最少次数显然是BFS,有些恶心的是存路径。这里也写了一下DFS。
①DFS:过19个点

#include <iostream>
#include <algorithm>
#include <cstring>
#define x first
#define y second
using namespace std;
const int N = 210;
typedef pair<int, int> PII;
PII q[N],ans[N];
int a, b;
int n, m, k;
int cnt,  res = 0x3f3f3f3f;
bool st[N][N];
void dfs(int x,int y)
{
    if(cnt>res) return;
    if(x==k||y==k)
    {
        if(cnt<res)
        {
            res=cnt;
            for(int i=1;i<=res;i++) ans[i]=q[i];
        }
        return;
    }
    for(int i=1;i<=2;i++)
        for(int j=1;j<=3;j++)
        {
            int ix=x,iy=y;
            if(i==1&&j==1&&!st[n][y]) ix=n;
            else if(i==1&&j==2&&!st[0][y]) ix=0;
            else if(i==1&&j==3&&!st[max(x-m+y,(int)0)][min(y,x+y)])
            {ix=max(x-m+y,(int)0);iy=min(m,x+y);}
            else if(i==2&&j==1&&!st[x][m]) iy=m;
            else if(i==2&&j==2&&!st[x][0]) iy=0;
            else if(i==2&&j==3&&!st[min(n,x+y)][max(x-n+y,(int)0)])
            {ix=min(n,x+y);iy=max(x-n+y,(int)0);}
            else continue;//否则会直接爆栈
            q[++cnt]={i,j};
            st[ix][iy]=true;
            dfs(ix,iy);
            cnt--;st[ix][iy]=false;
        }
}
int main()
{
    cin >> n >> m >> k;
    st[0][0] = true;
    dfs(0, 0);
    if (res == 0x3f3f3f3f) puts("impossible");
    else
    {
        cout<<res<<endl;
        for(int i=1;i<=res;i++) //cout<<ans[i].y<<' '<<ans[i].x<<endl;
            if(ans[i].y==1) printf("FILL(%d)\n",ans[i].x);
            else if(ans[i].y==2) printf("DROP(%d)\n",ans[i].x);
            else if(ans[i].y==3) 
            {
                int xx=0,yy=0;
                if(ans[i].x==1) {xx=1;yy=2;}
                else {xx=2;yy=1;}
                printf("POUR(%d,%d)\n",xx,yy);
            }
    }
    return 0;
}

②BFS:AC

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define x first
#define y second
using namespace std;
const int N = 210;
typedef pair<int, int> PII;
int n, m, k,d[N][N],dd=1e9;
vector<PII>ans;
struct node
{
    int x,y;
    vector<PII>v;
}s[N];
void bfs()
{
    memset(d,-1,sizeof d);
    queue<node>q;d[0][0]=0;
    vector<PII>vv;vv.push_back({0,0});q.push({0,0,vv});
    while(q.size())
    {
        node t=q.front();q.pop();
        vector<PII>vvv=t.v;
        if(t.x==k||t.y==k)
        {
            if(dd>d[t.x][t.y])
            {
                dd=d[t.x][t.y];
                ans=vvv;
            }
            return;
        }
        for(int i=1;i<=2;i++)
            for(int j=1;j<=3;j++)
            {
                vvv=t.v;
                if(i==1&&j==1&&d[n][t.y]==-1)
                {
                    vvv.push_back({i,j});
                    q.push({n,t.y,vvv});
                    d[n][t.y]=d[t.x][t.y]+1;
                }
                else if(i==1&&j==2&&d[0][t.y]==-1) 
                {
                    vvv.push_back({i,j});
                    q.push({0,t.y,vvv});
                    d[0][t.y]=d[t.x][t.y]+1;
                }
                else if(i==1&&j==3&&d[max(t.x-m+t.y,0)][min(m,t.x+t.y)]==-1) 
                {
                    vvv.push_back({i,j});
                    q.push({max(t.x-m+t.y,0),min(m,t.x+t.y),vvv});
                    d[max(t.x-m+t.y,0)][min(m,t.x+t.y)]=d[t.x][t.y]+1;
                }
                else if(i==2&&j==1&&d[t.x][m]==-1) 
                {
                    vvv.push_back({i,j});
                    q.push({t.x,m,vvv});
                    d[t.x][m]=d[t.x][t.y]+1;
                }
                else if(i==2&&j==2&&d[t.x][0]==-1) 
                {
                    vvv.push_back({i,j});
                    q.push({t.x,0,vvv});
                    d[t.x][0]=d[t.x][t.y]+1;
                }
                else if(i==2&&j==3&&d[min(n,t.x+t.y)][max(t.x-n+t.y,0)]==-1)
                {
                    vvv.push_back({i,j});
                    q.push({min(n,t.x+t.y),max(t.x-n+t.y,0),vvv});
                    d[min(n,t.x+t.y)][max(t.x-n+t.y,0)]=d[t.x][t.y]+1;
                }
            }
    }
}
int main()
{
    cin >> n >> m >> k;
    bfs();
    if(dd==1e9) cout<<"impossible\n";
    else cout<<dd<<endl;
    for(int i=1;i<ans.size();i++) 
    {
        if(ans[i].y==1) printf("FILL(%d)\n",ans[i].x);
        else if(ans[i].y==2) printf("DROP(%d)\n",ans[i].x);
        else
        {
            if(ans[i].x==2) printf("POUR(2,1)\n");
            else printf("POUR(1,2)\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值