分析:注意这里求的是最少流量, 二不是最少步数!!!所以我们用优先队列去维护一个最小流量,然后进行bfs即可,解释一下一个重要的数组ans[i],表示的是杯子中的水为i时的最小流量
1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "queue" 5 #include "algorithm" 6 using namespace std; 7 const int maxn=200+10; 8 int a,b,c,d,T; 9 int vis[maxn][maxn],ans[maxn],cap[3]; //ans[i]表示杯子中有i升水时对应的最少倒水量 10 struct Node{ 11 int v[3],dist; 12 bool operator < (const Node & rsh) const{ //小顶堆 13 return dist>rsh.dist; 14 } 15 }; 16 17 void update(const Node & u){ //更新ans[] 18 for(int i=0;i<3;i++){ 19 int s=u.v[i]; 20 if(ans[s]<0||u.dist<ans[s]) ans[s]=u.dist; 21 } 22 } 23 24 void bfs(int a,int b,int c,int d){ 25 memset(vis,0,sizeof(vis)); 26 memset(ans,-1,sizeof(ans)); 27 cap[0]=a,cap[1]=b,cap[2]=c; 28 Node start; 29 start.dist=0; 30 start.v[0]=0,start.v[1]=0,start.v[2]=c; 31 priority_queue<Node>que; 32 vis[0][0]=1; 33 que.push(start); 34 while(!que.empty()){ 35 Node u=que.top(); que.pop(); 36 update(u); 37 if(ans[d]>=0) break; //如果找到了 38 for(int i=0;i<3;i++){ 39 for(int j=0;j<3;j++) if(i!=j){ //自己不能和自己匹配 40 if(u.v[i]==0||u.v[j]==cap[j]) continue; 41 int num=min(cap[j],u.v[i]+u.v[j])-u.v[j]; 42 Node u2; 43 memcpy(&u2,&u,sizeof(u)); 44 u2.v[i]-=num; 45 u2.v[j]+=num; 46 u2.dist=u.dist+num; 47 if(!vis[u2.v[0]][u2.v[1]]){ //如果当前状态没有出现过 48 vis[u2.v[0]][u2.v[1]]=1; 49 que.push(u2); 50 } 51 } 52 } 53 } 54 while(d>=0){ 55 if(ans[d]>=0){ 56 printf("%d %d\n",ans[d],d); 57 return ; 58 } 59 --d; 60 } 61 } 62 int main() 63 { 64 scanf("%d",&T); 65 while(T--){ 66 scanf("%d%d%d%d",&a,&b,&c,&d); 67 bfs(a,b,c,d); 68 } 69 return 0; 70 }
时间: 2024-11-05 16:24:02