题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495
题目大意:一瓶S的可乐,两个容量分别为N和M的杯子,三者能够相互倾倒可乐,并且S=M+N,问是否能得到相同的两份可乐。如果能的话就计算最少的操作步数。
题解:就是有六种操作,然后就用常规bfs来做。每种操作额外考虑一下能否倒完就好了。
2021/3/16 (新帖简洁代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -f; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
const int maxN = 101;
int ini[3], mid;
bool vis[maxN][maxN][maxN];
int dir[6][2] = {
0, 1,
0, 2,
1, 0,
1, 2,
2, 0,
2, 1
};
struct node{
int a[3], dis;
};
int bfs() {
queue<node>q;
q.push(node{{ini[0], 0, 0}, 0});
vis[ini[0]][0][0] = true;
while(!q.empty()) {
node tmp = q.front(); q.pop();
for(int i = 0; i < 6; ++ i ) {
node New = tmp; New.dis += 1;
int fir = dir[i][0], sec = dir[i][1];
int dif = min(New.a[fir], ini[sec] - New.a[sec]);
New.a[fir] -= dif, New.a[sec] += dif;
if(vis[New.a[0]][New.a[1]][New.a[2]]) continue;
q.push(New);
vis[New.a[0]][New.a[1]][New.a[2]] = true;
if(New.a[0] == New.a[2] && New.a[0] == mid && New.a[1] == 0) return New.dis;
if(New.a[1] == New.a[2] && New.a[1] == mid && New.a[0] == 0) return New.dis;
if(New.a[0] == New.a[1] && New.a[0] == mid && New.a[2] == 0) return New.dis;
}
}
return -1;
}
int main() {
while(~scanf("%d%d%d", &ini[0], &ini[1], &ini[2]) && (ini[0] || ini[1] || ini[2])) {
if(ini[0] & 1) {
puts("NO");
continue;
}
memset(vis, false, sizeof(vis));
if(ini[1] > ini[2]) swap(ini[1], ini[2]);
mid = ini[0] >> 1;
int ans = bfs();
if(ans == -1) {
puts("NO");
continue;
}
printf("%d\n", ans);
}
return 0;
}
FEELING:debug了很久,本来昨天做了一道类似的而且还比这个难,但是这个还是做了一个多小时,debug了贼久,然后最后发现是有个最后一种操作的字母有地方写错了,天呐,也真的是……不然另一道题就开出来了,室友等我回去还是要走了,呜呜呜,伤心……
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <math.h>
#include <string.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f
const int MAX=0x3f3f3f3f;
using namespace std;
typedef long long ll;
int S,N,M;
struct node{
int s,n,m;//当前状态
int step;//步数
};
int mp[105][105][105];
int bfs(int es,int en,int em)
{
memset(mp,false,sizeof(mp));
node temp;
temp.s=es;
temp.n=en;
temp.m=em;
temp.step=0;
queue<node>q;
q.push(temp);
mp[q.front().s][q.front().n][q.front().m]=1;
while(!q.empty())
{
for(int i=0;i<6;i++)
{
if(i==0)//S->N
{
//如果能倒完
if(q.front().s<=N-q.front().n)
{
temp.n=q.front().n+q.front().s;
temp.s=0;
temp.m=q.front().m;
}
//如果不能倒完
else if(q.front().s>N-q.front().n)
{
temp.s=q.front().s-(N-q.front().n);
temp.n=N;
temp.m=q.front().m;
}
}
else if(i==1)//S->M
{
//如果能倒完
if(q.front().s<=M-q.front().m)
{
temp.m=q.front().m+q.front().s;
temp.s=0;
temp.n=q.front().n;
}
//如果不能倒完
else if(q.front().s>M-q.front().m)
{
temp.s=q.front().s-(M-q.front().m);
temp.m=M;
temp.n=q.front().n;
}
}
else if(i==2)//N->S
{
//如果能倒完
if(q.front().n<=S-q.front().s)
{
temp.s=q.front().n+q.front().s;
temp.n=0;
temp.m=q.front().m;
}
//如果不能倒完
else if(q.front().n>S-q.front().s)
{
temp.n=q.front().n-(S-q.front().s);
temp.s=S;
temp.m=q.front().m;
}
}
else if(i==3)//N->M
{
//如果能倒完
if(q.front().n<=M-q.front().m)
{
temp.m=q.front().n+q.front().m;
temp.n=0;
temp.s=q.front().s;
}
//如果不能倒完
else if(q.front().n>M-q.front().m)
{
temp.n=q.front().n-(M-q.front().m);
temp.m=M;
temp.s=q.front().s;
}
}
else if(i==4)//M->S
{
//如果能倒完
if(q.front().m<=S-q.front().s)
{
temp.s=q.front().m+q.front().s;
temp.m=0;
temp.n=q.front().n;
}
//如果不能倒完
else if(q.front().m>S-q.front().s)
{
temp.m=q.front().m-(S-q.front().s);
temp.s=S;
temp.n=q.front().n;
}
}
else if(i==5)//M->N
{
//如果能倒完
if(q.front().m<=N-q.front().n)
{
temp.n=q.front().n+q.front().m;
temp.m=0;
temp.s=q.front().s;
}
//如果不能倒完
else if(q.front().m>N-q.front().n)
{
temp.m=q.front().m-(N-q.front().n);
temp.n=N;
temp.s=q.front().s;
}
}
if(mp[temp.s][temp.n][temp.m]==1)
continue;
temp.step=q.front().step+1;
q.push(temp);
mp[temp.s][temp.n][temp.m]=1;
if((temp.s==temp.n&&temp.m==0)||(temp.s==temp.m&&temp.n==0)||(temp.m==temp.n&&temp.s==0))
return temp.step;
}
q.pop();
}
return 0;
}
int main()
{
while(~scanf("%d%d%d",&S,&N,&M)&&(S||N||M))
{
int ans=bfs(S,0,0);
if(ans==0)
printf("NO\n");
else
printf("%d\n",ans);
}
return 0;
}