刚拿到这题时很纠结,没有思路。后来想了一天,问了问高手终于把思路整理出来。
思路:三个瓶子,无非就是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;
}