uva 10603(BFS+优先队列)

先吐槽下这两天无限卡题,已经积了3道了。一筹莫展,只能先开一道稍微简单点的。

题意:这题就是加强版的倒水问题,把三个杯子分别含水量作为状态,已经倒水的值作为距离。构建隐式图,然后利用优先队列宽搜其中记得时刻更新到达终点的最小距离。因为有可能无法到达目标状态需要输出离目标最近的。其实状态还可进一步简化,由于总的水量是一定的,所以只要记录两个杯子的含水量就可推出第三个。我这里没有简化,代码也写得比较长。。。terrible。不过至少1A了

代码如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <algorithm>
  7 #include <queue>
  8 #include <stack>
  9 #include <vector>
 10 #define MP(a, b) make_pair(a, b)
 11 #define PB(a) push_back(a)
 12 
 13 using namespace std;
 14 
 15 typedef long long ll;
 16 typedef pair<int ,int> pii;
 17 typedef pair<unsigned int, unsigned int> puu;
 18 typedef pair<int ,double> pid;
 19 typedef pair<ll, int> pli;
 20 
 21 const int INF = 0x3f3f3f3f;
 22 const double eps = 1e-6;
 23 const int LEN = 201;
 24 
 25 struct S{int a[3];};
 26 typedef pair<int, S> pis;
 27 int ed, dis[LEN][LEN][LEN];
 28 bool vis[LEN][LEN][LEN];
 29 S st;
 30 
 31 inline void setd(S &vex, int val){dis[vex.a[0]][vex.a[1]][vex.a[2]] = val;}
 32 inline int getd(S vex){return dis[vex.a[0]][vex.a[1]][vex.a[2]];}
 33 inline void svis(S vex){vis[vex.a[0]][vex.a[1]][vex.a[2]] = 1;}
 34 inline bool isvis(S vex){return vis[vex.a[0]][vex.a[1]][vex.a[2]]==true;}
 35 inline int cv(int val){return val>0?val:INF;}
 36 struct cmp
 37 {
 38     bool operator()(pis x, pis y){return x.first > y.first;}
 39 };
 40 
 41 //将水从a倒到b中
 42 S pour(S vex, int a, int b, int &val)
 43 {
 44     int rest = st.a[b]-vex.a[b], water = vex.a[a];
 45     if(water>rest){
 46         vex.a[b] = st.a[b];
 47         vex.a[a]-=rest;
 48     }else{
 49         vex.a[b]+=water;
 50         vex.a[a] = 0;
 51     }
 52     val = min(water, rest);
 53     return vex;
 54 }
 55 
 56 
 57 void BFS(S s)
 58 {
 59     priority_queue<pis, vector<pis>, cmp> q;
 60     int y, mindip = INF, mp[3];
 61     memset(dis, 0x3f, sizeof dis);
 62     memset(vis, 0, sizeof vis);
 63     setd(s, 0);
 64     q.push(MP(getd(s), s));
 65     svis(s);
 66     while(!q.empty()){
 67         pis nvex = q.top(); q.pop();
 68         S nv = nvex.second;
 69         if(nv.a[0]==ed || nv.a[1]==ed || nv.a[2]==ed){
 70             printf("%d %d
", getd(nv), ed);
 71             return ;
 72         }
 73         if(min(cv(ed-nv.a[0]), min(cv(ed-nv.a[1]),cv(ed-nv.a[2])))<mindip){
 74             mindip = min(cv(ed-nv.a[0]), min(cv(ed-nv.a[1]),cv(ed-nv.a[2])));
 75             for(int i=0; i<3; i++)mp[i] = nv.a[i];
 76         }
 77         for(int i=0; i<3; i++)
 78         for(int j=0; j<3; j++){
 79             if(i==j || !nv.a[i])continue;
 80             S av = pour(nv, i, j, y);
 81             if(!isvis(av)){
 82                 svis(av);
 83                 setd(av, getd(nv)+y);
 84                 q.push(MP(getd(av), av));
 85             }
 86         }
 87     }
 88     printf("%d %d
", dis[mp[0]][mp[1]][mp[2]], ed-mindip);
 89 }
 90 
 91 int main()
 92 {
 93 //    freopen("in.txt", "r", stdin);
 94 
 95     int T;
 96     scanf("%d", &T);
 97     while(T--){
 98         for(int i=0; i<3; i++) scanf("%d", &st.a[i]);
 99         scanf("%d", &ed);
100         BFS((S){0,0,st.a[2]});
101     }
102     return 0;
103 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3511587.html