HDU1495 非常可乐(BFS)

  刚拿到这题时很纠结,没有思路。后来想了一天,问了问高手终于把思路整理出来。

思路:三个瓶子,无非就是6种倒法,按杯子体积从大到小定义为s, m, n。则6种倒法分别是:s -> m, s -> n, m -> n, m -> s,  n -> m, n -> s;

加一个标记变量,标记当前状态已经出现过。将没出现过的状态入队列,剩下的就是bfs的事了。。。

My Code:

#include <iostream>
#include
<cstdio>
#include
<cstring>

using namespace std;
const int N = 100000;
struct coco
{
int s;
int m;
int n;
int step;
}q[N];

int s, m, n;
int vis[101][101];

int bfs()
{
coco p, t;
int cnt, r = 0, f = 0;
q[
0].s = s;
q[
0].m = 0;
q[
0].n = 0;
q[
0].step = 0;
vis[m][n]
= 1;
r
++;
while(f < r)
{
p
= q[f++];
cnt
= 0;
if(p.s == s/2) cnt++;
if(p.m == s/2) cnt++;
if(p.n == s/2) cnt++;
if(cnt == 2) //satisfied the term
return p.step;
if(p.s)
{
t
= p;
if(t.m < m) //s -> m
{
if(t.m + t.s > m)
{
t.s
-= (m-t.m);
t.m
= m;
}
else
{
t.m
+= t.s;
t.s
= 0;
}
t.step
++;
if(!vis[p.m][p.n])
{
vis[p.m][p.n]
= 1;
q[r
++] = t;
}
}
t
= p;
if(t.n < n) //s -> n
{
if(t.n + t.s > n)
{
t.s
-= (n-t.n);
t.n
= n;
}
else
{
t.m
+= t.s;
t.s
= 0;
}
t.step
++;
if(!vis[t.m][t.n])
{
vis[t.m][t.n]
= 1;
q[r
++] = t;
}
}
}
if(p.m)
{
t
= p; //m -> n
if(t.n < n)
{
if(t.n + t.m > n)
{
t.m
-= (n-t.n);
t.n
= n;
}
else
{
t.n
+= t.m;
t.m
= 0;
}
t.step
++;
if(!vis[t.m][t.n])
{
vis[t.m][t.n]
= 1;
q[r
++] = t;
}
}

t
= p; // m -> s
t.s += t.m;
t.m
= 0;
t.step
++;
if(!vis[t.m][t.n])
{
vis[t.m][t.n]
= 1;
q[r
++] = t;
}
}
if(p.n)
{
t
= p; // n -> m
if(t.n + t.m > m)
{
t.n
-= (m - t.m);
t.m
= m;
}
else
{
t.m
+= t.n;
t.n
= 0;
}
t.step
++;
if(!vis[t.m][t.n])
{
vis[t.m][t.n]
= 1;
q[r
++] = t;
}

t
= p; //n -> s
t.s += t.n;
t.n
= 0;
t.step
++;
if(!vis[t.m][t.n])
{
vis[t.m][t.n]
= 1;
q[r
++] = t;
}
}
}
return 0;
}

int main()
{
//freopen("data.in", "r", stdin);

int ans;
while(scanf("%d%d%d", &s, &n, &m), s||n||m)
{
memset(vis,
0, sizeof(vis));
if(m > n)
{
m
= m+n;
n
= m-n;
m
= m-n;
}
if(s&1) //if 's' is odd
{
printf(
"NO\n");
continue;
}
ans
= bfs();
if(ans)
printf(
"%d\n", ans);
else
printf(
"NO\n");
}
return 0;
}
原文地址:https://www.cnblogs.com/vongang/p/2164372.html