中文题就不翻译了,,
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1495
互相倒水的也是一种典型的搜索题,这里采取的是广搜的方法。
事先可以做一些优化,如果水体积是奇数那么肯定平分不了。取结构体为三个杯子里的水量,这是每执行一步操作后的状态。将初始状态压入队列里,每次计算所有可能的倒水情况,直到出现一种可以平分的状态,或是队列为空。
题目本身很好写,就是每步操作不像迷宫那样可以归到对一个数组的加减,这样代码本身比较冗长,比较考验耐心。
#include <iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; struct node { int s1,n1,m1; int step; friend bool operator < (node a,node b) {//定义结构体与结构体比较大小的方法 return b.step<a.step; } }; int vis[104][104][104]; int main() { int n,m,s; while(cin>>s>>n>>m) { priority_queue<node> q;//没卵用,直接用queue就好了 memset(vis,0,sizeof(vis)); if(s==0&&n==0&&m==0) break; if(n<m) swap(n,m); if(s%2) { cout<<"NO"<<endl; continue; } node buf,next; buf.s1=s;buf.n1=0;buf.m1=0; buf.step=0; q.push(buf); bool flag=false; while(!q.empty()) { buf=q.top(); q.pop(); if(buf.s1==s/2&&buf.n1==s/2) { cout<<buf.step<<endl; flag=true; break; } int num=min(buf.s1,n-buf.n1);//计算一步操作完成后3个杯子的水量 int n2=buf.n1+num,s2=buf.s1-num,m2=buf.m1; if(!vis[s2][n2][m2])//6种操作,每种差不多,但是都需要自己重写 { vis[s2][n2][m2]=1; next.n1=n2;next.m1=m2;next.s1=s2; next.step=buf.step+1; q.push(next); } num=min(buf.s1,m-buf.m1); m2=buf.m1+num,s2=buf.s1-num,n2=buf.n1; if(!vis[s2][n2][m2]) { vis[s2][n2][m2]=1; next.n1=n2;next.m1=m2;next.s1=s2; next.step=buf.step+1; q.push(next); } num=min(buf.n1,m-buf.m1); m2=buf.m1+num,s2=buf.s1,n2=buf.n1-num; if(!vis[s2][n2][m2]) { vis[s2][n2][m2]=1; next.n1=n2;next.m1=m2;next.s1=s2; next.step=buf.step+1; q.push(next); } num=min(buf.n1,s-buf.s1); m2=buf.m1,s2=buf.s1+num,n2=buf.n1-num; if(!vis[s2][n2][m2]) { vis[s2][n2][m2]=1; next.n1=n2;next.m1=m2;next.s1=s2; next.step=buf.step+1; q.push(next); } num=min(buf.m1,s-buf.s1); m2=buf.m1-num,s2=buf.s1+num,n2=buf.n1; if(!vis[s2][n2][m2]) { vis[s2][n2][m2]=1; next.n1=n2;next.m1=m2;next.s1=s2; next.step=buf.step+1; q.push(next); } num=min(buf.m1,n-buf.n1); m2=buf.m1-num,s2=buf.s1,n2=buf.n1+num; if(!vis[s2][n2][m2]) { vis[s2][n2][m2]=1; next.n1=n2;next.m1=m2;next.s1=s2; next.step=buf.step+1; q.push(next); } } if(flag==false) cout<<"NO"<<endl; } }