题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495
题意:一罐可乐容积s,两个杯子n,m。求最小的倒水次数使其平分。
思路:直接用BFS模拟,数据很小,不用担心会T,此处输出NO的情况为s是技术以及ans输出为0 的情况。
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cstring>
#include <malloc.h>
#include <queue>
#include <map>
#include <set>
using namespace std;
const int maxn = 102;
struct node
{
int a,b,c,d;
node(){}
node(int e,int f,int g,int h):a(e),b(f),c(g),d(h){}
}ss,ns;
bool vis[maxn][maxn][maxn];
int s,n,m;
int bfs()
{
int a,b,c,d;
queue<node> que;
que.push(node(s,0,0,0));
vis[s][0][0]=1;
while(que.size()){
ss=que.front();que.pop();
a=ss.a,b=ss.b,c=ss.c,d=ss.d;
if(a==s/2||b==s/2||c==s/2) {return d+(a&&b&&c!=0);}//注意不是出现一个均分的杯子就行了,必须是分别用两个杯子装一般的可乐。留意一下第二个样例就行
if(vis[a+b-n][n][c]==0){
que.push(node(a+b-n,n,c,d+1));
vis[a+b-n][n][c]=1;
}//将s中的可乐倒到第一个杯子,以下也是相同的模拟办法
if(!vis[a+c-m][b][m]){
que.push(node(a+c-m,b,m,d+1));
vis[a+c-m][b][m]=1;
}
if(!vis[a+b][0][c]){
vis[a+b][0][c]=1;
que.push(node(a+b,0,c,d+1));
}
if(!vis[a+c][b][0]){
vis[a+c][b][0]=1;
que.push(node(a+c,b,0,d+1));
}
//其实可以在这里做一个a,b的swap比较好
if(n>b+c){
if(!vis[a][b+c][0]){
vis[a][b+c][0]=1;
que.push(node(a,b+c,0,d+1));
}
}
else{
if(!vis[a][n][b+c-n]){
vis[a][n][b+c-n]=1;
que.push(node(a,n,b+c-n,d+1));
}
}
if(m>b+c){
if(!vis[a][0][c+b]){
vis[a][0][c+b]=1;
que.push(node(a,0,c+b,d+1));
}
}
else{
if(!vis[a][b+c-m][m]){
vis[a][b+c-m][m]=1;
que.push(node(a,b+c-m,m,d+1));
}
}
}
return 0;
}
int main()
{
cin.tie(0);
ios::sync_with_stdio(0);
while(cin>>s>>n>>m){
if(!n&&!m&&!s) break;
memset(vis,0,sizeof(vis));
int ans=bfs();
if(s&1||!ans) cout<<"NO"<<endl;
else
cout<<ans<<endl;
}
}
其实考虑到速度的话可以考虑在外边写一个倒水函数可以简化很多行。
另外也看到有大神用数论做出来了。膜。
http://blog.csdn.net/v5zsq/article/details/52097459