要注意题目的意思,由样例 4 1 3 答案是3 ,可以推测,题目是要求将可乐分为两等份放在两个容器中。
由于当S为奇数时一定无解,所以只有当S为偶数时进行处理。可以使用二维数组进行判重,因为可乐总数是确定的,知道两个容器中的可乐量就能知道第三个容器中的可乐量。
实现在三个容器中倒可乐的方式有点复杂,还好不久之前看紫书时刚好记下来一个方法。要注意理解。
AC代码如下:
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int vis[110][110],cup[3];
struct Node{
int v[3],d;
bool operator () (int a,int b,int c,int e){v[0]=a,v[1]=b,v[2]=c,d=e;return 1;}
//重载运算符,要有返回值,不然在一些oj上会报error
};
int bfs(){
int g=cup[0]/2; //目标状态
queue<Node> que;
Node fi,n,u;
fi(cup[0],0,0,0);
que.push(fi);
memset(vis,0,sizeof(vis));
vis[cup[0]][cup[1]]=1;
while(!que.empty()){
n=que.front();
que.pop();
if((n.v[0]==g&&n.v[1]==g)||(n.v[1]==g&&n.v[2]==g)||(n.v[0]==g&&n.v[2]==g)) return n.d;
//成功分为两等分
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){ //cup[i]向cup[j]倒水
if(i!=j){
u=n;
int amount=min(cup[j],n.v[i]+n.v[j])-n.v[j];
//cup[j]能接收的水量
u.d=n.d+1;
u.v[i]-=amount;
u.v[j]+=amount;
if(u.v[i]<0||u.v[j]<0||vis[u.v[0]][u.v[1]]) continue;
vis[u.v[0]][u.v[1]]=1;
que.push(u);
}
}
}
}
return 0;
}
int main(){
//freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&cup[0],&cup[1],&cup[2])&&cup[0]){
if(cup[0]%2){printf("NO\n");continue;} //奇数不处理
int ans=bfs();
if(ans) printf("%d\n",ans);
else printf("NO\n");
}
return 0;
}