HDU1495,广搜

来源:互联网 发布:爱知时计科技有限公司 编辑:程序博客网 时间:2024/04/28 10:01

其实这是一道比较常规的搜索题,思路也很符合搜索的想法(搜索其实就是暴力出所有结果,然后选取满足条件的结果);我感觉这题就难在写代码上;

好了,先说思路吧:首先对于这三个容器(s->可乐瓶,a->杯子1,b->杯子2),只有以下几种情况:s往a里到可乐,s往b里倒可乐,a往s里倒可乐,a往b里倒可乐,b往s里倒可乐,b往a里倒可乐。所以直接暴力BFS就行了(代码详解)

#include<cstdio>#include<iostream>#include<queue>#include<cstring>#include<cstdlib>using namespace std;int vis[105][105][105];//搜索标记用的,三维数组,没用过没关系,这里用的很简单int n,x,y;//n可乐瓶的容积,x是杯子a的容积,y是杯子b的容积struct node{    int s,a,b;    int mov;};//每个结构体,用来保存当前这种情况s,a,b中可乐的多少,mov表示由初始情况到这种情况需要倒的次数queue<node>q;//BFS用的队列int bfs(node start){    while (!q.empty())        q.pop();//队列清空    q.push(start);//初始状态入队列    while (!q.empty())    {        node tmp = q.front();        q.pop();        node next;        if (tmp.s != 0)//s中有可乐(接下来往a,b中倒)        {            //下面是往a杯子中倒可乐            if (tmp.s <= x - tmp.a)//x是a杯子的容积,tmp.a是该状态下,a容器中可乐的量,它们                //的差就是a杯子中还能装多少可乐;这条判断的意思是,s中的可乐量小于a杯子还能装的可乐量            {                //s往a中倒完之后的状态就是:                next.s = 0;                next.a = tmp.a + tmp.s;                next.b = tmp.b;            }            else//这条判断的意思是,s中的可乐量大于于a杯子还能装的可乐量            {                next.s = tmp.s - (x-tmp.a);                next.a = x;                next.b = tmp.b;            }            next.mov = tmp.mov + 1;//由刚开始状态到倒完之后的状态,倒的次数+1            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))            {                //这条判断就是看在倒完之后得到的状态下,有没有两个容器中可乐的量都=n/2的                return next.mov;            }            if (!vis[next.s][next.a][next.b])//如果没有两个容器中可乐的量都=n/2的话,就入队列,同时标记一下这种状态            {                q.push(next);                vis[next.s][next.a][next.b] = 1;            }            //下面是s往b中倒可乐,情况同上            if (tmp.s <= y - tmp.b)            {                next.s = 0;                next.a = tmp.a;                next.b = tmp.s + tmp.b;            }            else            {                next.s = tmp.s - (y-tmp.b);                next.a = tmp.a;                next.b = y;            }            next.mov = tmp.mov + 1;            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))            {                return next.mov;            }            if (!vis[next.s][next.a][next.b])            {                q.push(next);                vis[next.s][next.a][next.b] = 1;            }        }        if (tmp.a != 0)//a中有可乐(接下来往s,b中倒)        {            //下面是a往b中倒可乐            if (tmp.a <= y - tmp.b)            {                next.a = 0;                next.b = tmp.a + tmp.b;            }            else            {                next.a = tmp.a - (y-tmp.b);                next.b = y;            }            next.s = tmp.s;            next.mov = tmp.mov + 1;            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))            {                return next.mov;            }            if (!vis[next.s][next.a][next.b])            {                q.push(next);                vis[next.s][next.a][next.b] = 1;            }            //下面是a往s中倒可乐            next.s = tmp.s + tmp.a;            next.a = 0;            next.b = tmp.b;            next.mov = tmp.mov + 1;            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))            {                return next.mov;            }            if (!vis[next.s][next.a][next.b])            {                q.push(next);                vis[next.s][next.a][next.b] = 1;            }        }        if (tmp.b != 0)//所有情况和上面两种情况一样        {            if (tmp.b <= x - tmp.a)            {                next.a = tmp.a + tmp.b;                next.b = 0;            }            else            {                next.a = x;                next.b = tmp.b - (x-tmp.a);            }            next.s = tmp.s;            next.mov = tmp.mov + 1;            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))            {                return next.mov;            }            if (!vis[next.s][next.a][next.b])            {                q.push(next);                vis[next.s][next.a][next.b] = 1;            }            next.s = tmp.s + tmp.b;            next.a = tmp.a;            next.b = 0;            next.mov = tmp.mov + 1;            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))            {                return next.mov;            }            if (!vis[next.s][next.a][next.b])            {                q.push(next);                vis[next.s][next.a][next.b] = 1;            }        }    }    return -1;//如果在这之前函数没有返回值的话,说明不可均分}int main(){    while (~scanf("%d%d%d",&n,&x,&y))    {        if (n+x+y == 0)            break;        if(n % 2 != 0)        {            printf("NO\n");            continue;        }        //这三个容器的体积都是整数,所以可乐体积的一半如果是小数的话,每人是不可能分到的,就输出NO        memset(vis,0,sizeof(vis));//标记数组先都清成0        node tmp;//建立一个节点,保存最开始的状态        tmp.s = n;//最开始,所有可乐在s中        tmp.a = 0;//最开始,a杯子中没有可乐        tmp.b = 0;//最开始,b杯子中没有可乐        tmp.mov = 0;//倒的次数为0        vis[n][x][y] = 1;//标记数组的三个数分别就是s,a,b中的可乐量        int ans = bfs(tmp);        if (ans == -1)//返回-1,表明了不可均分            printf("NO\n");        else            printf("%d\n",ans);    }    return 0;}


0 0