传送门:HDU1495
中文题意就不说了。
思路:这题被挂到搜索专题里,可我怎么想也想不出来该咋搜,其实还是思路太窄,原来做的搜索题大部分都是走迷宫什么的。。思路被限制住了,但看了题解发现这里bfs的状态转移实际上并不难,在走迷宫之类的问题中,每个点都是一种状态,状态都是从一个点朝四个方向进行转移,这里三个杯子的水量是一种状态,只不过状态转移换成了把水从哪个杯子倒向哪个杯子的问题,一共有六种情况S->N N->S S->M M->S M->N N->M,只要每次bfs取出一种状态来,进行这六种状态转移,再放入队列就好了,还有要注意的一点是标记数组开二维就够了,分别N和M两个杯子中的水量,当然,这里数据量小开三维也无所谓。
PS:为了方便讨论六种情况,最好提前确定N和M哪个是较大的杯子,这里我取N为较大的杯子。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>P;
int s,n,m;
int book[110][110];
struct node{
int n,m,s;
int step;
};
//s->n ;s->m ; n->s ; n->m ;m->s ;m->n
void bfs()
{
memset(book,0,sizeof(book));
queue<node>q;
while(!q.empty())
q.pop();
q.push({0,0,s,0});
while(!q.empty())
{
node t=q.front(),a;
a.step=t.step+1;
q.pop();
if(t.n==s>>1&&t.s==s>>1)
{
printf("%d\n",t.step);
return ;
}
if(t.s+t.n<=n)//s->n
{
a.n=t.s+t.n;
a.s=0;
a.m=t.m;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
else
{
a.n=n;
a.s=t.s+t.n-n;
a.m=t.m;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
if(t.s+t.m<=m)//s->m
{
a.m=t.s+t.m;
a.s=0;
a.n=t.n;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
else
{
a.m=m;
a.s=t.s+t.m-m;
a.n=t.n;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
a.s=t.s+t.n;//n->s
a.n=0;
a.m=t.m;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
a.s=t.s+t.m;//m->s
a.m=0;
a.n=t.n;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
if(t.m+t.n<=m)//n->m
{
a.m=t.m+t.n;
a.n=0;
a.s=t.s;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
else
{
a.m=m;
a.n=t.n+t.m-m;
a.s=t.s;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
if(t.m+t.n<=n)//m->n
{
a.n=t.m+t.n;
a.m=0;
a.s=t.s;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
else
{
a.n=n;
a.m=t.n+t.m-n;
a.s=t.s;
if(!book[a.n][a.m])
{
q.push(a);
book[a.n][a.m]=1;
}
}
}
printf("NO\n");
return ;
}
int main()
{
while(scanf("%d%d%d",&s,&n,&m)&&s+n+m)
{
if(s&1)//奇数肯定无法等分
{
printf("NO\n");
continue;
}
if(n<m)
swap(n,m);
bfs();
}
return 0;
}
六种情况稍微细心一点并不难写。
心得:怪不得某学长说DP和bfs有联系,原来还搞不明白这两者能有啥联系,不过从这个题看来,二者本质都是确定了初始状态和状态转移关系之后,对衍生状态的一种枚举,不过DP的思想更凝练些,而bfs更通俗易懂罢了。