题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1495/
题意:给定三个杯子S,M,N,满足S=M+N,现在要求用最短的次数将S杯中的饮倒平分到两个杯子中。我们首先想到这个问题需要用搜索来解决,由于杯子没有刻度,所以每次倒水都是要将一个杯子中的水倒光或者将另一个杯子倒满,我们就这样在状态空间中搜索,直到check通过。由于是根据倒水的次数进行的层次搜索,所以最终确定的倒水次数一定是最少的次数。这道题竟然因为“NO”的“O”没有大写被卡,心态爆炸,什么是否能不写奇奇怪怪的bug ~T^T。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define dbg(args) cout<<#args<<":"<<args<<endl; 17 #define inf 0x3f3f3f3f 18 #define maxn 105 19 int s,n,m,t; 20 int ans=0; 21 int vol[3]; 22 bool vis[maxn][maxn];//用两个杯子的容量即可确定三个被子的容量 23 struct node{ 24 int v[3],step; 25 node(int a,int b,int c,int s){ 26 v[0]=a,v[1]=b,v[2]=c,step=s; 27 } 28 node(){} 29 }; 30 node cur,nxt; 31 void pour(node &a,int i,int j) 32 { 33 int tmp=min(a.v[i],vol[j]-a.v[j]); 34 a.v[i]-=tmp; 35 a.v[j]+=tmp; 36 } 37 int bfs() 38 { 39 if(s%2)return -1; 40 queue<node>q; 41 q.push(node(s,0,0,0)); 42 vis[s][0]=1; 43 int k=s/2; 44 while(!q.empty()) 45 { 46 cur=q.front(); 47 q.pop(); 48 if((cur.v[0]==k&&cur.v[1]==k)||(cur.v[0]==k&&cur.v[2]==k)||(cur.v[1]==k&&cur.v[2]==k)) 49 { 50 // cout<<cur.v[0]<<cur.v[1]<<cur.v[2]<<endl; 51 return cur.step; 52 } 53 f(i,0,2) 54 f(j,0,2) 55 { 56 if(i==j)continue; 57 nxt=cur; 58 pour(nxt,i,j); 59 if(!vis[nxt.v[0]][nxt.v[1]]) 60 { 61 vis[nxt.v[0]][nxt.v[1]]=1; 62 nxt.step++; 63 q.push(nxt); 64 } 65 } 66 } 67 return -1; 68 } 69 int main() 70 { 71 //freopen("input.txt","r",stdin); 72 //freopen("output.txt","w",stdout); 73 std::ios::sync_with_stdio(false); 74 while(scanf("%d%d%d",&s,&n,&m)&&s&&m&&n) 75 { 76 vol[0]=s; 77 vol[1]=n; 78 vol[2]=m; 79 mem(vis,false); 80 ans=bfs(); 81 if(ans==-1) 82 { 83 pf("NO "); 84 } 85 else pf("%d ",ans); 86 } 87 }