优先队列-UVA10603
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 typedef struct state STA; 6 struct state 7 { 8 int cup[3],water; 9 bool operator< (const state p)const 10 {//优先队列的核心其实在于队列内元素的排列顺序,也就是自定义变量的 < 定义 11 return this->water > p.water; 12 } 13 }; 14 15 priority_queue<STA> psd; 16 const int maxn = 300; 17 int vis[maxn][maxn];//采取二维数组的原因之一是:所有状态的可能总数很少 18 int ans[maxn]; 19 int maxcup[3],aimd; 20 21 int update_ans(STA& p) 22 { 23 for(int i=0;i<3;i++) 24 { 25 int t=p.cup[i]; 26 if(ans[t]==-1||ans[t]>p.water)ans[t]=p.water; 27 } 28 return 0; 29 } 30 31 int bfs() 32 { 33 while(!psd.empty())psd.pop(); 34 memset(vis,0,sizeof(vis)); 35 memset(ans,-1,sizeof(ans)); 36 scanf("%d%d%d%d",&maxcup[0],&maxcup[1],&maxcup[2],&aimd); 37 //printf("%d %d %d %d\n",maxcup[0],maxcup[1],maxcup[2],aimd); 38 STA p; 39 p.cup[0]=0;p.cup[1]=0; 40 p.water=0;p.cup[2]=maxcup[2]; 41 vis[0][0]=1; 42 int d=aimd; 43 // 44 psd.push(p); 45 while(!psd.empty()) 46 { 47 p=psd.top();psd.pop(); 48 update_ans(p); 49 if(ans[d]>=0)break; 50 //倒水 51 for(int i=0;i<3;i++) 52 { 53 for(int k=0;k<3;k++) 54 {//i与k分别是出水杯与进水杯 55 if(i==k)continue; 56 if(p.cup[i]==0||p.cup[k]==maxcup[k])continue; 57 /*很重要的规律*/ int pour_water=min(maxcup[k],p.cup[i]+p.cup[k])-p.cup[k]; 58 STA u; 59 memcpy(&u,&p,sizeof(p)); 60 u.cup[i]-=pour_water; 61 u.cup[k]+=pour_water; 62 u.water+=pour_water; 63 // 64 if(!vis[u.cup[0]][u.cup[1]]) 65 {//由于总水量一定,只要已知其中两个变量就能确定其状态 66 vis[u.cup[0]][u.cup[1]]=1; 67 psd.push(u); 68 }//if 69 }//in for 70 }//out for 71 }//while 72 // 73 while(d>=0) 74 { 75 if(ans[d]>=0){printf("%d %d\n",ans[d],d);break;} 76 else d--;//接近d,从现实的角度而言只能比d小 77 } 78 return 0; 79 } 80 81 int main() 82 { 83 //freopen("input.txt","r",stdin); 84 //freopen("ans.txt","w",stdout); 85 int n; 86 scanf("%d",&n); 87 //printf("n is %d\n",n); 88 while(n--)bfs(); 89 return 0; 90 }