题意就是给你仨瓶子,一个是可乐瓶,两个空瓶,三个都能用,你要倒来倒去来用两个瓶子平分第一个瓶里的可乐,但是倒的时候只能把瓶子倒满。输出平分需要的最少步骤,若不能输出NO;
广搜把每一步的结果都记录下来,自己可以找点小数据在纸上试试就明白了,代码有点长思路很清晰。注意一下标记就可以了,没有太大坑点,主要在理解。
#include <stdio.h> #include <iostream> #include <algorithm> #include <queue> #include <string.h> #include <stack> #define LL long long #define mem(a) memset(a,0,sizeof(a)) int M,N,S,vis[105][105][105]; struct node { int s,n,m,step; }; std::queue<node> q; int bfs() { node a,t; int i,k; mem(vis); while(q.size()) q.pop(); a.s=S; a.m=0; a.n=0; a.step=0; q.push(a); vis[a.s][0][0]=1; while(q.size()) { a=q.front(); q.pop(); if(a.s==S/2&&a.m==S/2||a.s==S/2&&a.n==S/2||a.m==S/2&&a.n==S/2) return a.step; for(i=0;i<6;i++)//倒可乐的循环步骤,光看是不容易理解的,自己找数据亲自试试,想想 { if(i==0)///S-->M { k=a.s<(M-a.m)?a.s:(M-a.m); t.s=a.s-(M-a.m); t.m=a.m+k; t.n=a.n; } else if(i==1)///M-->S { k=a.m<(S-a.s)?a.m:(S-a.s); t.s=a.s+k; t.m=a.m-k; t.n=a.n; } else if(i==2)///S-->N { k=a.s<(N-a.n)?a.s:(N-a.n); t.s=a.s-k; t.n=a.n+k; t.m=a.m; } else if(i==3)///N-->S { k=a.n<(S-a.s)?a.n:(S-a.s); t.s=a.s+k; t.n=a.n-k; t.m=a.m; } else if(i==4)///M-->N { k=a.m<(N-a.n)?a.m:(N-a.n); t.s=a.s; t.m=a.m-k; t.n=a.n+k; } else///N-->M { k=a.n<(M-a.m)?a.n:(M-a.m); t.s=a.s; t.m=a.m+k; t.n=a.n-k; } if(!vis[t.s][t.m][t.n]) { t.step=a.step+1; vis[t.s][t.m][t.n]=1; q.push(t); } } } return -1; } int main() { while(scanf("%d%d%d",&S,&N,&M),M+S+N) { if(S%2>0) printf("NO "); else { int k=bfs(); if(k!=-1) printf("%d ",k); else printf("NO "); } } return 0; }