kuangbin 简单搜索 - POJ - 3414 Pots (bfs)

kuangbin 简单搜索 - POJ - 3414 Pots (bfs)

在这里插入图片描述
在这里插入图片描述

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>

#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
//#define int ll
#define INF 0x3f3f3f3f
using namespace std;
int read()
{
	int w = 1, s = 0;
	char ch = getchar();
	while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0';    ch = getchar(); }
	return s * w;
//最大公约数
}int gcd(int x,int y) {
    if(x<y) swap(x,y);//很多人会遗忘,大数在前小数在后
    //递归终止条件千万不要漏了,辗转相除法
    return x % y ? gcd(y, x % y) : y;
}
int lcm(int x,int y)//计算x和y的最小公倍数
{
    return x * y / gcd(x, y);//使用公式
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//
const int N = 110;
int a,b,c,top;
int vis[N][N];
struct node
{
    int x,y;//状态
    int w; //当前步骤
    int last;//上一个状态
    int step;//需要多少个步骤
}ans[1000000];
void pri(int x) //六种方法打印
{
    if(x==0)
        printf("FILL(1)\n");
    if(x==1)
        printf("FILL(2)\n");
    if(x==2)
        printf("POUR(2,1)\n");
    if(x==3)
        printf("POUR(1,2)\n");
    if(x==4)
        printf("DROP(1)\n");
    if(x==5)
        printf("DROP(2)\n");
}
void yes(int x) //回溯
{
    if(ans[x].last==0)
    {
        pri(ans[x].w);
        return ;
    }
    yes(ans[x].last);
    pri(ans[x].w);
}
void bfs()
{
    int head,tail,i;
    int aa,bb;
    head = 0,tail = 1;
    while(head<=tail) //模拟队列
    {
        node x = ans[head++];
        if(x.x==c||x.y==c) //成功
        {
            cout<<ans[head-1].step<<endl;
            yes(head-1);
            return ;
        }
        for(i=0;i<6;i++) //六种操作
        {
            if(i==0)
            {
                aa = a;
                bb = x.y;
            }
            if(i==1)
            {
                aa = x.x;
                bb = b;
            }
            if(i==2)
            {
                aa = min(a,x.x+x.y);
                bb = max(0,x.y-(a-x.x));
            }
            if(i==3)
            {
                aa = max(0,x.x-(b-x.y));
                bb = min(b,x.x+x.y);
            }
            if(i==4)
            {
                aa = 0;
                bb = x.y;
            }
            if(i==5)
            {
                aa = x.x;
                bb = 0;
            }
            if(!vis[aa][bb])
            {
                ans[tail].x = aa;
                ans[tail].y = bb;
                ans[tail].w = i;
                ans[tail].step = x.step+1;
                ans[tail++].last = head-1;
                vis[aa][bb] = 1;
            }
        }
    }
    cout<<"impossible"<<endl;
}
int main()
{
    int i;
    while(cin>>a>>b>>c)
    {
        memset(vis,0,sizeof(vis));
        top = 0;
        ans[top].x = 0;
        ans[top].y = 0;
        ans[top].step = 0;
        ans[top++].last = 0; //初始状态为空
        vis[0][0] = 1;
        bfs();
    }
    return 0;
}

题意:
给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作
FILL(i) 将第i个容器从水龙头里装满(1 ≤ i ≤ 2);
DROP(i) 将第i个容器抽干
POUR(i,j) 将第i个容器里的水倒入第j个容器(这次操作结束后产生两种结果,一是第j个容器倒满并且第i个容器依旧有剩余,二是第i个容器里的水全部倒入j中,第i个容器为空)
现在要求你写一个程序,来找出能使其中任何一个容器里的水恰好有C升,找出最少操作数并给出操作过程

题解:
求最小操作次数并输出,BFS,六种情况,分别讨论6种情况:

  1. 倒满a
  2. 倒满b
  3. 把a里的水倒向b(两种情况b倒满a有剩余或者a倒完)
  4. 把b里的水倒向a(类似2的两种情况)
  5. 把a倒空
  6. 把b倒空
    分别求这6种情况即可。
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页