版权声明:版权归Ordinarv所有 https://blog.csdn.net/ordinarv/article/details/82180410
题目大意
三个cup,容量分别为s,n,m(s=n+m),cup没有刻度(这个真的坑,就是要么倒完要么倒满)。初始状况,s满,n、m空,求能否通过相互之间倒可乐,把可乐平分。能的话,输出最小次数。
分析
每次倒都有6种情况s-n,s-m.....。可以BFS分别枚举每种倒法。很明显s为奇数,NO。
vis也能起到终止作用吧,每种情况都走过被标记了。队列为空,则返回-1,表示不能平分。
要注意 只有当下一状态条件满足并且没有走过时,才让其level+1;
听说数论也能做,但我 不会!
AC Code
#include<bits/stdc++.h>
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e2+5;
using namespace std;
int s,n,m;
bool vis[maxn][maxn][maxn];
struct node {
int s,m,n,level;
};
bool judge(node &tar) {
int ans=s/2;
if(tar.s==ans&&tar.n==ans||tar.s==ans&&tar.m==ans||tar.n==ans&&tar.m==ans)
return 1;
return 0;
}
int bfs() {
if(s%2) return -1;
memset(vis,0,sizeof(vis));
queue<node> q;
node cur,next;
cur.s=s;
cur.n=0;
cur.m=0;
cur.level=0;
vis[s][0][0]=1;
q.push(cur);
while(!q.empty()) {
cur=q.front();
q.pop();
//6 zhong
if(cur.s&&n-cur.n>0) { //s->n
if(cur.s>=(n-cur.n)) { //s能够倒满n
next.s=cur.s-(n-cur.n);
next.n=n;
}
else {
next.s=0;
next.n=cur.n+cur.s;
}
next.m=cur.m;
if(!vis[next.s][next.n][next.m]) {
next.level=cur.level+1;//要放入if里
vis[next.s][next.n][next.m]=1;
q.push(next);
}
if(judge(next)) return next.level;
}
//s->m
if(cur.s&&n-cur.m>0) { //s->n
if(cur.s>=(m-cur.m)) {
next.s=cur.s-(m-cur.m);
next.m=m;
}
else {
next.s=0;
next.m=cur.m+cur.s;
}
next.n=cur.n;
if(!vis[next.s][next.n][next.m]) {
next.level=cur.level+1;
vis[next.s][next.n][next.m]=1;
q.push(next);
}
if(judge(next)) return next.level;
}
//n->s
if(cur.n&&s-cur.s>0) { //s->n
if(cur.n>=(s-cur.s)) {
next.n=cur.n-(s-cur.s);
next.s=s;
}
else {
next.n=0;
next.s=cur.s+cur.n;
}
next.m=cur.m;
if(!vis[next.s][next.n][next.m]) {
next.level=cur.level+1;
vis[next.s][next.n][next.m]=1;
q.push(next);
}
if(judge(next)) return next.level;
}
//n->m
if(cur.n&&m-cur.m>0) { //s->n
if(cur.n>=(m-cur.m)) {
next.n=cur.n-(m-cur.m);
next.m=m;
}
else {
next.n=0;
next.m=cur.m+cur.n;
}
next.s=cur.s;
if(!vis[next.s][next.n][next.m]) {
next.level=cur.level+1;
vis[next.s][next.n][next.m]=1;
q.push(next);
}
if(judge(next)) return next.level;
}
//m->s
if(cur.m&&s-cur.s>0) { //s->n
if(cur.m>=(s-cur.s)) {
next.m=cur.m-(s-cur.s);
next.s=s;
}
else {
next.m=0;
next.s=cur.s+cur.m;
}
next.n=cur.n;
if(!vis[next.s][next.n][next.m]) {
next.level=cur.level+1;
vis[next.s][next.n][next.m]=1;
q.push(next);
}
if(judge(next)) return next.level;
}
//m->n
if(cur.m&&n-cur.n>0) { //s->n
if(cur.m>=(n-cur.n)) {
next.m=cur.m-(n-cur.n);
next.n=n;
}
else {
next.m=0;
next.n=cur.n+cur.m;
}
next.s=cur.s;
if(!vis[next.s][next.n][next.m]) {
next.level=cur.level+1;//要放入if里
vis[next.s][next.n][next.m]=1;
q.push(next);
}
if(judge(next)) return next.level;
}
}
return -1;
}
int main() {
while(~scanf("%d%d%d",&s,&n,&m)&&s+m+n) {
int ans=bfs();
if(ans==-1) printf("NO\n");
else printf("%d\n",ans);
}
return 0;
}