您的位置:首页 > 其它

HDU1495,广搜

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

好了,先说思路吧:首先对于这三个容器(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
[x][y] = 1;//标记数组的三个数分别就是s,a,b中的可乐量
int ans = bfs(tmp);
if (ans == -1)//返回-1,表明了不可均分
printf("NO\n");
else
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU1495 非常可乐