优先队列-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 }

 

posted @ 2020-01-26 17:34  SavenNeer  阅读(174)  评论(0编辑  收藏  举报